Merge pull request #6410 from BlueWallet/refactor-app-storage

REF: app-storage class
This commit is contained in:
GLaDOS 2024-04-17 00:19:39 +00:00 committed by GitHub
commit 1f34f5137d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 180 additions and 166 deletions

View File

@ -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

View 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;

View File

@ -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]);

View File

@ -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;

View File

@ -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();

View File

@ -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';

View File

@ -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) {

View File

@ -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));

View File

@ -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

View File

@ -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');
});