mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-01-19 14:45:17 +01:00
Merge pull request #6410 from BlueWallet/refactor-app-storage
REF: app-storage class
This commit is contained in:
commit
1f34f5137d
@ -1,6 +1,8 @@
|
||||
import { getUniqueId } from 'react-native-device-info';
|
||||
import Bugsnag from '@bugsnag/react-native';
|
||||
import BlueApp from '../BlueApp';
|
||||
import { BlueApp as BlueAppClass } from '../class';
|
||||
|
||||
const BlueApp = BlueAppClass.getInstance();
|
||||
|
||||
/**
|
||||
* in case Bugsnag was started, but user decided to opt out while using the app, we have this
|
||||
|
69
blue_modules/start-and-decrypt.ts
Normal file
69
blue_modules/start-and-decrypt.ts
Normal file
@ -0,0 +1,69 @@
|
||||
import { Platform } from 'react-native';
|
||||
import Biometric from '../class/biometrics';
|
||||
import prompt from '../helpers/prompt';
|
||||
import loc from '../loc';
|
||||
import { BlueApp as BlueAppClass } from '../class/';
|
||||
|
||||
const BlueApp = BlueAppClass.getInstance();
|
||||
// If attempt reaches 10, a wipe keychain option will be provided to the user.
|
||||
let unlockAttempt = 0;
|
||||
|
||||
export const startAndDecrypt = async (retry?: boolean): Promise<boolean> => {
|
||||
console.log('startAndDecrypt');
|
||||
if (BlueApp.getWallets().length > 0) {
|
||||
console.log('App already has some wallets, so we are in already started state, exiting startAndDecrypt');
|
||||
return true;
|
||||
}
|
||||
await BlueApp.migrateKeys();
|
||||
let password: undefined | string;
|
||||
if (await BlueApp.storageIsEncrypted()) {
|
||||
do {
|
||||
password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted, false);
|
||||
} while (!password);
|
||||
}
|
||||
let success = false;
|
||||
let wasException = false;
|
||||
try {
|
||||
success = await BlueApp.loadFromDisk(password);
|
||||
} catch (error) {
|
||||
// in case of exception reading from keystore, lets retry instead of assuming there is no storage and
|
||||
// proceeding with no wallets
|
||||
console.warn('exception loading from disk:', error);
|
||||
wasException = true;
|
||||
}
|
||||
|
||||
if (wasException) {
|
||||
// retrying, but only once
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000)); // sleep
|
||||
success = await BlueApp.loadFromDisk(password);
|
||||
} catch (error) {
|
||||
console.warn('second exception loading from disk:', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
console.log('loaded from disk');
|
||||
// We want to return true to let the UnlockWith screen that its ok to proceed.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (password) {
|
||||
// we had password and yet could not load/decrypt
|
||||
unlockAttempt++;
|
||||
if (unlockAttempt < 10 || Platform.OS !== 'ios') {
|
||||
return startAndDecrypt(true);
|
||||
} else {
|
||||
unlockAttempt = 0;
|
||||
Biometric.showKeychainWipeAlert();
|
||||
// We want to return false to let the UnlockWith screen that it is NOT ok to proceed.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
unlockAttempt = 0;
|
||||
// Return true because there was no wallet data in keychain. Proceed.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
export default BlueApp;
|
@ -1,18 +1,20 @@
|
||||
import React, { createContext, useEffect, useState } from 'react';
|
||||
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
|
||||
|
||||
import BlueApp, { TTXMetadata, startAndDecrypt } from '../BlueApp';
|
||||
import { startAndDecrypt } from './start-and-decrypt';
|
||||
import Notifications from '../blue_modules/notifications';
|
||||
import { LegacyWallet, WatchOnlyWallet } from '../class';
|
||||
import { LegacyWallet, TTXMetadata, WatchOnlyWallet, BlueApp as BlueAppClass } from '../class';
|
||||
import type { TWallet } from '../class/wallets/types';
|
||||
import presentAlert from '../components/Alert';
|
||||
import loc, { STORAGE_KEY as LOC_STORAGE_KEY } from '../loc';
|
||||
import { FiatUnit, TFiatUnit } from '../models/fiatUnit';
|
||||
import * as BlueElectrum from './BlueElectrum';
|
||||
import { PREFERRED_CURRENCY_STORAGE_KEY } from './currency';
|
||||
import { initCurrencyDaemon, PREFERRED_CURRENCY_STORAGE_KEY } from './currency';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from './hapticFeedback';
|
||||
import A from '../blue_modules/analytics';
|
||||
|
||||
const BlueApp = BlueAppClass.getInstance();
|
||||
|
||||
// hashmap of timestamps we _started_ refetching some wallet
|
||||
const _lastTimeTriedToRefetchWallet: { [walletID: string]: number } = {};
|
||||
|
||||
@ -97,6 +99,7 @@ export const BlueStorageProvider = ({ children }: { children: React.ReactNode })
|
||||
|
||||
useEffect(() => {
|
||||
if (walletsInitialized) {
|
||||
initCurrencyDaemon();
|
||||
BlueElectrum.connectMain();
|
||||
}
|
||||
}, [walletsInitialized]);
|
||||
|
@ -1,38 +1,29 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import createHash from 'create-hash';
|
||||
import { Platform } from 'react-native';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
import * as Keychain from 'react-native-keychain';
|
||||
import { Transaction, TWallet } from './wallets/types';
|
||||
import RNSecureKeyStore, { ACCESSIBLE } from 'react-native-secure-key-store';
|
||||
import Realm from 'realm';
|
||||
import { initCurrencyDaemon } from './blue_modules/currency';
|
||||
import * as encryption from './blue_modules/encryption';
|
||||
import {
|
||||
HDAezeedWallet,
|
||||
HDLegacyBreadwalletWallet,
|
||||
HDLegacyElectrumSeedP2PKHWallet,
|
||||
HDLegacyP2PKHWallet,
|
||||
HDSegwitBech32Wallet,
|
||||
HDSegwitElectrumSeedP2WPKHWallet,
|
||||
HDSegwitP2SHWallet,
|
||||
LegacyWallet,
|
||||
LightningCustodianWallet,
|
||||
LightningLdkWallet,
|
||||
MultisigHDWallet,
|
||||
SLIP39LegacyP2PKHWallet,
|
||||
SLIP39SegwitBech32Wallet,
|
||||
SLIP39SegwitP2SHWallet,
|
||||
SegwitBech32Wallet,
|
||||
SegwitP2SHWallet,
|
||||
WatchOnlyWallet,
|
||||
} from './class/';
|
||||
import Biometric from './class/biometrics';
|
||||
import { randomBytes } from './class/rng';
|
||||
import { TWallet, Transaction } from './class/wallets/types';
|
||||
import presentAlert from './components/Alert';
|
||||
import prompt from './helpers/prompt';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import * as encryption from '../blue_modules/encryption';
|
||||
import createHash from 'create-hash';
|
||||
import RNFS from 'react-native-fs';
|
||||
import loc from './loc';
|
||||
import Realm from 'realm';
|
||||
import Keychain from 'react-native-keychain';
|
||||
import { randomBytes } from './rng';
|
||||
import presentAlert from '../components/Alert';
|
||||
import { SegwitBech32Wallet } from './wallets/segwit-bech32-wallet';
|
||||
import { SegwitP2SHWallet } from './wallets/segwit-p2sh-wallet';
|
||||
import { WatchOnlyWallet } from './wallets/watch-only-wallet';
|
||||
import { HDLegacyP2PKHWallet } from './wallets/hd-legacy-p2pkh-wallet';
|
||||
import { HDSegwitP2SHWallet } from './wallets/hd-segwit-p2sh-wallet';
|
||||
import { HDSegwitBech32Wallet } from './wallets/hd-segwit-bech32-wallet';
|
||||
import { HDLegacyBreadwalletWallet } from './wallets/hd-legacy-breadwallet-wallet';
|
||||
import { HDLegacyElectrumSeedP2PKHWallet } from './wallets/hd-legacy-electrum-seed-p2pkh-wallet';
|
||||
import { HDSegwitElectrumSeedP2WPKHWallet } from './wallets/hd-segwit-electrum-seed-p2wpkh-wallet';
|
||||
import { MultisigHDWallet } from './wallets/multisig-hd-wallet';
|
||||
import { HDAezeedWallet } from './wallets/hd-aezeed-wallet';
|
||||
import { LightningLdkWallet } from './wallets/lightning-ldk-wallet';
|
||||
import { SLIP39LegacyP2PKHWallet, SLIP39SegwitBech32Wallet, SLIP39SegwitP2SHWallet } from './wallets/slip39-wallets';
|
||||
import { LightningCustodianWallet } from './wallets/lightning-custodian-wallet';
|
||||
import { LegacyWallet } from './wallets/legacy-wallet';
|
||||
import DefaultPreference from 'react-native-default-preference';
|
||||
|
||||
let usedBucketNum: boolean | number = false;
|
||||
let savingInProgress = 0; // its both a flag and a counter of attempts to write to disk
|
||||
@ -52,14 +43,16 @@ type TRealmTransaction = {
|
||||
|
||||
const isReactNative = typeof navigator !== 'undefined' && navigator?.product === 'ReactNative';
|
||||
|
||||
export class AppStorage {
|
||||
export class BlueApp {
|
||||
static FLAG_ENCRYPTED = 'data_encrypted';
|
||||
static LNDHUB = 'lndhub';
|
||||
static ADVANCED_MODE_ENABLED = 'advancedmodeenabled';
|
||||
static DO_NOT_TRACK = 'donottrack';
|
||||
static HANDOFF_STORAGE_KEY = 'HandOff';
|
||||
|
||||
static keys2migrate = [AppStorage.HANDOFF_STORAGE_KEY, AppStorage.DO_NOT_TRACK, AppStorage.ADVANCED_MODE_ENABLED];
|
||||
private static _instance: BlueApp | null = null;
|
||||
|
||||
static keys2migrate = [BlueApp.HANDOFF_STORAGE_KEY, BlueApp.DO_NOT_TRACK, BlueApp.ADVANCED_MODE_ENABLED];
|
||||
|
||||
public cachedPassword?: false | string;
|
||||
public tx_metadata: TTXMetadata;
|
||||
@ -71,13 +64,21 @@ export class AppStorage {
|
||||
this.cachedPassword = false;
|
||||
}
|
||||
|
||||
static getInstance(): BlueApp {
|
||||
if (!BlueApp._instance) {
|
||||
BlueApp._instance = new BlueApp();
|
||||
}
|
||||
|
||||
return BlueApp._instance;
|
||||
}
|
||||
|
||||
async migrateKeys() {
|
||||
// do not migrate keys if we are not in RN env
|
||||
if (!isReactNative) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key of AppStorage.keys2migrate) {
|
||||
for (const key of BlueApp.keys2migrate) {
|
||||
try {
|
||||
const value = await RNSecureKeyStore.get(key);
|
||||
if (value) {
|
||||
@ -135,9 +136,9 @@ export class AppStorage {
|
||||
storageIsEncrypted = async (): Promise<boolean> => {
|
||||
let data;
|
||||
try {
|
||||
data = await this.getItemWithFallbackToRealm(AppStorage.FLAG_ENCRYPTED);
|
||||
data = await this.getItemWithFallbackToRealm(BlueApp.FLAG_ENCRYPTED);
|
||||
} catch (error: any) {
|
||||
console.warn('error reading `' + AppStorage.FLAG_ENCRYPTED + '` key:', error.message);
|
||||
console.warn('error reading `' + BlueApp.FLAG_ENCRYPTED + '` key:', error.message);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -199,7 +200,7 @@ export class AppStorage {
|
||||
data = JSON.stringify(data);
|
||||
this.cachedPassword = password;
|
||||
await this.setItem('data', data);
|
||||
await this.setItem(AppStorage.FLAG_ENCRYPTED, '1');
|
||||
await this.setItem(BlueApp.FLAG_ENCRYPTED, '1');
|
||||
};
|
||||
|
||||
/**
|
||||
@ -414,7 +415,7 @@ export class AppStorage {
|
||||
unserializedWallet = LightningCustodianWallet.fromJson(key) as unknown as LightningCustodianWallet;
|
||||
let lndhub: false | any = false;
|
||||
try {
|
||||
lndhub = await AsyncStorage.getItem(AppStorage.LNDHUB);
|
||||
lndhub = await AsyncStorage.getItem(BlueApp.LNDHUB);
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
}
|
||||
@ -683,12 +684,12 @@ export class AppStorage {
|
||||
}
|
||||
|
||||
await this.setItem('data', JSON.stringify(data));
|
||||
await this.setItem(AppStorage.FLAG_ENCRYPTED, this.cachedPassword ? '1' : '');
|
||||
await this.setItem(BlueApp.FLAG_ENCRYPTED, this.cachedPassword ? '1' : '');
|
||||
|
||||
// now, backing up same data in realm:
|
||||
const realmkeyValue = await this.openRealmKeyValue();
|
||||
this.saveToRealmKeyValue(realmkeyValue, 'data', JSON.stringify(data));
|
||||
this.saveToRealmKeyValue(realmkeyValue, AppStorage.FLAG_ENCRYPTED, this.cachedPassword ? '1' : '');
|
||||
this.saveToRealmKeyValue(realmkeyValue, BlueApp.FLAG_ENCRYPTED, this.cachedPassword ? '1' : '');
|
||||
realmkeyValue.close();
|
||||
} catch (error: any) {
|
||||
console.error('save to disk exception:', error.message);
|
||||
@ -843,50 +844,50 @@ export class AppStorage {
|
||||
|
||||
isAdvancedModeEnabled = async (): Promise<boolean> => {
|
||||
try {
|
||||
return !!(await AsyncStorage.getItem(AppStorage.ADVANCED_MODE_ENABLED));
|
||||
return !!(await AsyncStorage.getItem(BlueApp.ADVANCED_MODE_ENABLED));
|
||||
} catch (_) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
setIsAdvancedModeEnabled = async (value: boolean) => {
|
||||
await AsyncStorage.setItem(AppStorage.ADVANCED_MODE_ENABLED, value ? '1' : '');
|
||||
await AsyncStorage.setItem(BlueApp.ADVANCED_MODE_ENABLED, value ? '1' : '');
|
||||
};
|
||||
|
||||
isHandoffEnabled = async (): Promise<boolean> => {
|
||||
try {
|
||||
return !!(await AsyncStorage.getItem(AppStorage.HANDOFF_STORAGE_KEY));
|
||||
return !!(await AsyncStorage.getItem(BlueApp.HANDOFF_STORAGE_KEY));
|
||||
} catch (_) {}
|
||||
return false;
|
||||
};
|
||||
|
||||
setIsHandoffEnabled = async (value: boolean): Promise<void> => {
|
||||
await AsyncStorage.setItem(AppStorage.HANDOFF_STORAGE_KEY, value ? '1' : '');
|
||||
await AsyncStorage.setItem(BlueApp.HANDOFF_STORAGE_KEY, value ? '1' : '');
|
||||
};
|
||||
|
||||
isDoNotTrackEnabled = async (): Promise<boolean> => {
|
||||
try {
|
||||
const keyExists = await AsyncStorage.getItem(AppStorage.DO_NOT_TRACK);
|
||||
const keyExists = await AsyncStorage.getItem(BlueApp.DO_NOT_TRACK);
|
||||
if (keyExists !== null) {
|
||||
const doNotTrackValue = !!keyExists;
|
||||
if (doNotTrackValue) {
|
||||
await DefaultPreference.setName('group.io.bluewallet.bluewallet');
|
||||
await DefaultPreference.set(AppStorage.DO_NOT_TRACK, '1');
|
||||
AsyncStorage.removeItem(AppStorage.DO_NOT_TRACK);
|
||||
await DefaultPreference.set(BlueApp.DO_NOT_TRACK, '1');
|
||||
AsyncStorage.removeItem(BlueApp.DO_NOT_TRACK);
|
||||
} else {
|
||||
return Boolean(await DefaultPreference.get(AppStorage.DO_NOT_TRACK));
|
||||
return Boolean(await DefaultPreference.get(BlueApp.DO_NOT_TRACK));
|
||||
}
|
||||
}
|
||||
} catch (_) {}
|
||||
const doNotTrackValue = await DefaultPreference.get(AppStorage.DO_NOT_TRACK);
|
||||
const doNotTrackValue = await DefaultPreference.get(BlueApp.DO_NOT_TRACK);
|
||||
return doNotTrackValue === '1' || false;
|
||||
};
|
||||
|
||||
setDoNotTrack = async (value: boolean) => {
|
||||
await DefaultPreference.setName('group.io.bluewallet.bluewallet');
|
||||
if (value) {
|
||||
await DefaultPreference.set(AppStorage.DO_NOT_TRACK, '1');
|
||||
await DefaultPreference.set(BlueApp.DO_NOT_TRACK, '1');
|
||||
} else {
|
||||
await DefaultPreference.clear(AppStorage.DO_NOT_TRACK);
|
||||
await DefaultPreference.clear(BlueApp.DO_NOT_TRACK);
|
||||
}
|
||||
};
|
||||
|
||||
@ -938,69 +939,3 @@ export class AppStorage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const BlueApp = new AppStorage();
|
||||
// If attempt reaches 10, a wipe keychain option will be provided to the user.
|
||||
let unlockAttempt = 0;
|
||||
|
||||
export const startAndDecrypt = async (retry?: boolean): Promise<boolean> => {
|
||||
console.log('startAndDecrypt');
|
||||
if (BlueApp.getWallets().length > 0) {
|
||||
console.log('App already has some wallets, so we are in already started state, exiting startAndDecrypt');
|
||||
return true;
|
||||
}
|
||||
await BlueApp.migrateKeys();
|
||||
let password: undefined | string;
|
||||
if (await BlueApp.storageIsEncrypted()) {
|
||||
do {
|
||||
password = await prompt((retry && loc._.bad_password) || loc._.enter_password, loc._.storage_is_encrypted, false);
|
||||
} while (!password);
|
||||
}
|
||||
let success = false;
|
||||
let wasException = false;
|
||||
try {
|
||||
success = await BlueApp.loadFromDisk(password);
|
||||
} catch (error) {
|
||||
// in case of exception reading from keystore, lets retry instead of assuming there is no storage and
|
||||
// proceeding with no wallets
|
||||
console.warn('exception loading from disk:', error);
|
||||
wasException = true;
|
||||
}
|
||||
|
||||
if (wasException) {
|
||||
// retrying, but only once
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 3000)); // sleep
|
||||
success = await BlueApp.loadFromDisk(password);
|
||||
} catch (error) {
|
||||
console.warn('second exception loading from disk:', error);
|
||||
}
|
||||
}
|
||||
|
||||
if (success) {
|
||||
console.log('loaded from disk');
|
||||
// We want to return true to let the UnlockWith screen that its ok to proceed.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (password) {
|
||||
// we had password and yet could not load/decrypt
|
||||
unlockAttempt++;
|
||||
if (unlockAttempt < 10 || Platform.OS !== 'ios') {
|
||||
return startAndDecrypt(true);
|
||||
} else {
|
||||
unlockAttempt = 0;
|
||||
Biometric.showKeychainWipeAlert();
|
||||
// We want to return false to let the UnlockWith screen that it is NOT ok to proceed.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
unlockAttempt = 0;
|
||||
// Return true because there was no wallet data in keychain. Proceed.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
initCurrencyDaemon();
|
||||
|
||||
export default BlueApp;
|
@ -5,11 +5,10 @@ import URL from 'url';
|
||||
|
||||
import { readFileOutsideSandbox } from '../blue_modules/fs';
|
||||
import { Chain } from '../models/bitcoinUnits';
|
||||
import { LightningCustodianWallet, WatchOnlyWallet } from './';
|
||||
import { BlueApp, LightningCustodianWallet, WatchOnlyWallet } from './';
|
||||
import Azteco from './azteco';
|
||||
import Lnurl from './lnurl';
|
||||
import type { TWallet } from './wallets/types';
|
||||
import { AppStorage } from '../BlueApp';
|
||||
|
||||
type TCompletionHandlerParams = [string, object];
|
||||
type TContext = {
|
||||
@ -232,7 +231,7 @@ class DeeplinkSchemaMatch {
|
||||
w.setLabel(w.typeReadable);
|
||||
|
||||
try {
|
||||
const lndhub = await AsyncStorage.getItem(AppStorage.LNDHUB);
|
||||
const lndhub = await AsyncStorage.getItem(BlueApp.LNDHUB);
|
||||
if (lndhub) {
|
||||
w.setBaseURI(lndhub);
|
||||
w.init();
|
||||
|
@ -18,3 +18,4 @@ export * from './wallets/multisig-hd-wallet';
|
||||
export * from './wallets/slip39-wallets';
|
||||
export * from './hd-segwit-bech32-transaction';
|
||||
export * from './multisig-cosigner';
|
||||
export * from './blue-app';
|
@ -12,7 +12,7 @@ import DeeplinkSchemaMatch from '../../class/deeplink-schema-match';
|
||||
import presentAlert from '../../components/Alert';
|
||||
import { requestCameraAuthorization } from '../../helpers/scan-qr';
|
||||
import { Button } from '../../components/Button';
|
||||
import { AppStorage } from '../../BlueApp';
|
||||
import { BlueApp } from '../../class';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
uri: {
|
||||
@ -62,7 +62,7 @@ const LightningSettings: React.FC & { navigationOptions: NavigationOptionsGetter
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
AsyncStorage.getItem(AppStorage.LNDHUB)
|
||||
AsyncStorage.getItem(BlueApp.LNDHUB)
|
||||
.then(value => setURI(value ?? undefined))
|
||||
.then(() => setIsLoading(false))
|
||||
.catch(() => setIsLoading(false));
|
||||
@ -101,9 +101,9 @@ const LightningSettings: React.FC & { navigationOptions: NavigationOptionsGetter
|
||||
// validating only if its not empty. empty means use default
|
||||
}
|
||||
if (URI) {
|
||||
await AsyncStorage.setItem(AppStorage.LNDHUB, URI);
|
||||
await AsyncStorage.setItem(BlueApp.LNDHUB, URI);
|
||||
} else {
|
||||
await AsyncStorage.removeItem(AppStorage.LNDHUB);
|
||||
await AsyncStorage.removeItem(BlueApp.LNDHUB);
|
||||
}
|
||||
presentAlert({ message: loc.settings.lightning_saved });
|
||||
} catch (error) {
|
||||
|
@ -18,7 +18,14 @@ import {
|
||||
import { BlueButtonLink, BlueFormLabel, BlueSpacing20, BlueSpacing40, BlueText } from '../../BlueComponents';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
import { BlueStorageContext } from '../../blue_modules/storage-context';
|
||||
import { HDSegwitBech32Wallet, HDSegwitP2SHWallet, LightningCustodianWallet, LightningLdkWallet, SegwitP2SHWallet } from '../../class';
|
||||
import {
|
||||
BlueApp,
|
||||
HDSegwitBech32Wallet,
|
||||
HDSegwitP2SHWallet,
|
||||
LightningCustodianWallet,
|
||||
LightningLdkWallet,
|
||||
SegwitP2SHWallet,
|
||||
} from '../../class';
|
||||
import presentAlert from '../../components/Alert';
|
||||
import Button from '../../components/Button';
|
||||
import { LdkButton } from '../../components/LdkButton';
|
||||
@ -27,7 +34,6 @@ import { useTheme } from '../../components/themes';
|
||||
import useAsyncPromise from '../../hooks/useAsyncPromise';
|
||||
import loc from '../../loc';
|
||||
import { Chain } from '../../models/bitcoinUnits';
|
||||
import { AppStorage } from '../../BlueApp';
|
||||
import WalletButton from '../../components/WalletButton';
|
||||
import A from '../../blue_modules/analytics';
|
||||
|
||||
@ -143,7 +149,7 @@ const WalletsAdd: React.FC = () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
AsyncStorage.getItem(AppStorage.LNDHUB)
|
||||
AsyncStorage.getItem(BlueApp.LNDHUB)
|
||||
.then(url => (url ? setWalletBaseURI(url) : setWalletBaseURI('')))
|
||||
.catch(() => setWalletBaseURI(''))
|
||||
.finally(() => setIsLoading(false));
|
||||
|
@ -3,7 +3,7 @@ const path = require('path');
|
||||
|
||||
const mainLocFile = './loc/en.json';
|
||||
const dirsToInterate = ['components', 'screen', 'blue_modules', 'class', 'hooks', 'helpers'];
|
||||
const addFiles = ['BlueComponents.js', 'App.js', 'BlueApp.ts', 'Navigation.tsx'];
|
||||
const addFiles = ['BlueComponents.js', 'App.js', 'Navigation.tsx'];
|
||||
const allowedLocPrefixes = ['loc.lnurl_auth', 'loc.units'];
|
||||
|
||||
const allLocKeysHashmap = {}; // loc key -> used or not
|
||||
|
@ -1,7 +1,6 @@
|
||||
import assert from 'assert';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { SegwitP2SHWallet } from '../../class';
|
||||
import { AppStorage } from '../../BlueApp';
|
||||
import { SegwitP2SHWallet, BlueApp } from '../../class';
|
||||
|
||||
jest.mock('../../blue_modules/BlueElectrum', () => {
|
||||
return {
|
||||
@ -10,8 +9,8 @@ jest.mock('../../blue_modules/BlueElectrum', () => {
|
||||
});
|
||||
|
||||
it('Appstorage - loadFromDisk works', async () => {
|
||||
/** @type {AppStorage} */
|
||||
const Storage = new AppStorage();
|
||||
/** @type {BlueApp} */
|
||||
const Storage = new BlueApp();
|
||||
const w = new SegwitP2SHWallet();
|
||||
w.setLabel('testlabel');
|
||||
await w.generate();
|
||||
@ -20,7 +19,7 @@ it('Appstorage - loadFromDisk works', async () => {
|
||||
|
||||
// saved, now trying to load
|
||||
|
||||
const Storage2 = new AppStorage();
|
||||
const Storage2 = new BlueApp();
|
||||
await Storage2.loadFromDisk();
|
||||
assert.strictEqual(Storage2.wallets.length, 1);
|
||||
assert.strictEqual(Storage2.wallets[0].getLabel(), 'testlabel');
|
||||
@ -30,15 +29,15 @@ it('Appstorage - loadFromDisk works', async () => {
|
||||
// emulating encrypted storage (and testing flag)
|
||||
|
||||
await AsyncStorage.setItem('data', false);
|
||||
await AsyncStorage.setItem(AppStorage.FLAG_ENCRYPTED, '1');
|
||||
const Storage3 = new AppStorage();
|
||||
await AsyncStorage.setItem(BlueApp.FLAG_ENCRYPTED, '1');
|
||||
const Storage3 = new BlueApp();
|
||||
isEncrypted = await Storage3.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
});
|
||||
|
||||
it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
/** @type {AppStorage} */
|
||||
const Storage = new AppStorage();
|
||||
/** @type {BlueApp} */
|
||||
const Storage = new BlueApp();
|
||||
let w = new SegwitP2SHWallet();
|
||||
w.setLabel('testlabel');
|
||||
await w.generate();
|
||||
@ -53,7 +52,7 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
|
||||
// saved, now trying to load, using good password
|
||||
|
||||
let Storage2 = new AppStorage();
|
||||
let Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
let loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -63,7 +62,7 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
|
||||
// now trying to load, using bad password
|
||||
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('passwordBAD');
|
||||
@ -73,7 +72,7 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
// now, trying case with adding data after decrypt.
|
||||
// saveToDisk should be handled correctly
|
||||
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -88,7 +87,7 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
assert.strictEqual(Storage2.wallets[1].getLabel(), 'testlabel2');
|
||||
await Storage2.saveToDisk();
|
||||
// saved to encrypted storage after load. next load should be successfull
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -109,13 +108,13 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
await Storage2.saveToDisk();
|
||||
// now, will try to load & decrypt with real password and with fake password
|
||||
// real:
|
||||
let Storage3 = new AppStorage();
|
||||
let Storage3 = new BlueApp();
|
||||
loadResult = await Storage3.loadFromDisk('password');
|
||||
assert.ok(loadResult);
|
||||
assert.strictEqual(Storage3.wallets.length, 2);
|
||||
assert.strictEqual(Storage3.wallets[0].getLabel(), 'testlabel');
|
||||
// fake:
|
||||
Storage3 = new AppStorage();
|
||||
Storage3 = new BlueApp();
|
||||
loadResult = await Storage3.loadFromDisk('fakePassword');
|
||||
assert.ok(loadResult);
|
||||
assert.strictEqual(Storage3.wallets.length, 1);
|
||||
@ -123,8 +122,8 @@ it('Appstorage - encryptStorage & load encrypted storage works', async () => {
|
||||
});
|
||||
|
||||
it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load storage works', async () => {
|
||||
/** @type {AppStorage} */
|
||||
const Storage = new AppStorage();
|
||||
/** @type {BlueApp} */
|
||||
const Storage = new BlueApp();
|
||||
let w = new SegwitP2SHWallet();
|
||||
w.setLabel('testlabel');
|
||||
await w.generate();
|
||||
@ -139,7 +138,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
|
||||
// saved, now trying to load, using good password
|
||||
|
||||
let Storage2 = new AppStorage();
|
||||
let Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
let loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -149,7 +148,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
|
||||
// now trying to load, using bad password
|
||||
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('passwordBAD');
|
||||
@ -159,7 +158,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
// now, trying case with adding data after decrypt.
|
||||
// saveToDisk should be handled correctly
|
||||
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -174,7 +173,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
assert.strictEqual(Storage2.wallets[1].getLabel(), 'testlabel2');
|
||||
await Storage2.saveToDisk();
|
||||
// saved to encrypted storage after load. next load should be successfull
|
||||
Storage2 = new AppStorage();
|
||||
Storage2 = new BlueApp();
|
||||
isEncrypted = await Storage2.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage2.loadFromDisk('password');
|
||||
@ -195,13 +194,13 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
await Storage2.saveToDisk();
|
||||
// now, will try to load & decrypt with real password and with fake password
|
||||
// real:
|
||||
let Storage3 = new AppStorage();
|
||||
let Storage3 = new BlueApp();
|
||||
loadResult = await Storage3.loadFromDisk('password');
|
||||
assert.ok(loadResult);
|
||||
assert.strictEqual(Storage3.wallets.length, 2);
|
||||
assert.strictEqual(Storage3.wallets[0].getLabel(), 'testlabel');
|
||||
// fake:
|
||||
Storage3 = new AppStorage();
|
||||
Storage3 = new BlueApp();
|
||||
loadResult = await Storage3.loadFromDisk('fakePassword');
|
||||
assert.ok(loadResult);
|
||||
assert.strictEqual(Storage3.wallets.length, 1);
|
||||
@ -209,7 +208,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
|
||||
// now will decrypt storage. label of wallet should be testlabel
|
||||
|
||||
const Storage4 = new AppStorage();
|
||||
const Storage4 = new BlueApp();
|
||||
isEncrypted = await Storage4.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage4.loadFromDisk('password');
|
||||
@ -217,7 +216,7 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
const decryptStorageResult = await Storage4.decryptStorage('password');
|
||||
assert.ok(decryptStorageResult);
|
||||
|
||||
const Storage5 = new AppStorage();
|
||||
const Storage5 = new BlueApp();
|
||||
isEncrypted = await Storage5.storageIsEncrypted();
|
||||
assert.strictEqual(isEncrypted, false);
|
||||
const storage5loadResult = await Storage5.loadFromDisk();
|
||||
@ -228,8 +227,8 @@ it('Appstorage - encryptStorage & load encrypted, then decryptStorage and load s
|
||||
});
|
||||
|
||||
it('can decrypt storage that is second in a list of buckets; and isPasswordInUse() works', async () => {
|
||||
/** @type {AppStorage} */
|
||||
const Storage = new AppStorage();
|
||||
/** @type {BlueApp} */
|
||||
const Storage = new BlueApp();
|
||||
let w = new SegwitP2SHWallet();
|
||||
w.setLabel('testlabel');
|
||||
await w.generate();
|
||||
@ -256,7 +255,7 @@ it('can decrypt storage that is second in a list of buckets; and isPasswordInUse
|
||||
// now will decrypt storage. will try to decrypt FAKE storage (second in the list) while
|
||||
// currently decrypted is the MAIN (non-fake) storage. this should throw an exception
|
||||
|
||||
const Storage4 = new AppStorage();
|
||||
const Storage4 = new BlueApp();
|
||||
isEncrypted = await Storage4.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
let loadResult = await Storage4.loadFromDisk('password');
|
||||
@ -275,7 +274,7 @@ it('can decrypt storage that is second in a list of buckets; and isPasswordInUse
|
||||
// storage, purging other buckets. this should be possible since if user wants to shoot himsel in the foot
|
||||
// he should be able to do it.
|
||||
|
||||
const Storage5 = new AppStorage();
|
||||
const Storage5 = new BlueApp();
|
||||
isEncrypted = await Storage5.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage5.loadFromDisk('fakePassword');
|
||||
@ -288,7 +287,7 @@ it('can decrypt storage that is second in a list of buckets; and isPasswordInUse
|
||||
|
||||
// now we will decrypt storage. label of wallet should be testlabel
|
||||
|
||||
const Storage6 = new AppStorage();
|
||||
const Storage6 = new BlueApp();
|
||||
isEncrypted = await Storage6.storageIsEncrypted();
|
||||
assert.ok(isEncrypted);
|
||||
loadResult = await Storage6.loadFromDisk('fakePassword');
|
||||
@ -296,7 +295,7 @@ it('can decrypt storage that is second in a list of buckets; and isPasswordInUse
|
||||
const decryptStorageResult = await Storage6.decryptStorage('fakePassword');
|
||||
assert.ok(decryptStorageResult);
|
||||
|
||||
const Storage7 = new AppStorage();
|
||||
const Storage7 = new BlueApp();
|
||||
isEncrypted = await Storage7.storageIsEncrypted();
|
||||
assert.strictEqual(isEncrypted, false);
|
||||
const storage5loadResult = await Storage7.loadFromDisk();
|
||||
@ -305,6 +304,6 @@ it('can decrypt storage that is second in a list of buckets; and isPasswordInUse
|
||||
});
|
||||
|
||||
it('Appstorage - hashIt() works', async () => {
|
||||
const storage = new AppStorage();
|
||||
const storage = new BlueApp();
|
||||
assert.strictEqual(storage.hashIt('hello'), '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user