BlueWallet/blue_modules/storage-context.js

275 lines
9.2 KiB
JavaScript
Raw Normal View History

/* eslint-disable react/prop-types */
import React, { createContext, useEffect, useState } from 'react';
import { Alert } from 'react-native';
import ReactNativeHapticFeedback from 'react-native-haptic-feedback';
import { useAsyncStorage } from '@react-native-async-storage/async-storage';
2021-01-30 04:45:24 +01:00
import { FiatUnit } from '../models/fiatUnit';
import Notifications from '../blue_modules/notifications';
2021-05-18 22:38:18 +02:00
import loc from '../loc';
import { LegacyWallet } from '../class';
2021-09-22 18:07:13 +02:00
import { isTorDaemonDisabled, setIsTorDaemonDisabled } from './environment';
const BlueApp = require('../BlueApp');
const BlueElectrum = require('./BlueElectrum');
2021-05-18 22:38:18 +02:00
const currency = require('../blue_modules/currency');
const A = require('../blue_modules/analytics');
2021-01-01 20:15:40 +01:00
const _lastTimeTriedToRefetchWallet = {}; // hashmap of timestamps we _started_ refetching some wallet
2021-01-28 01:30:42 +01:00
export const WalletTransactionsStatus = { NONE: false, ALL: true };
export const BlueStorageContext = createContext();
export const BlueStorageProvider = ({ children }) => {
const [wallets, setWallets] = useState([]);
const [selectedWallet, setSelectedWallet] = useState('');
2021-01-28 01:30:42 +01:00
const [walletTransactionUpdateStatus, setWalletTransactionUpdateStatus] = useState(WalletTransactionsStatus.NONE);
const [walletsInitialized, setWalletsInitialized] = useState(false);
2021-01-30 04:45:24 +01:00
const [preferredFiatCurrency, _setPreferredFiatCurrency] = useState(FiatUnit.USD);
2020-12-13 10:52:54 +01:00
const [language, _setLanguage] = useState();
2021-05-18 22:38:18 +02:00
const getPreferredCurrencyAsyncStorage = useAsyncStorage(currency.PREFERRED_CURRENCY).getItem;
const getLanguageAsyncStorage = useAsyncStorage(loc.LANG).getItem;
2021-01-19 04:40:11 +01:00
const [isHandOffUseEnabled, setIsHandOffUseEnabled] = useState(false);
2021-08-24 07:00:57 +02:00
const [isElectrumDisabled, setIsElectrumDisabled] = useState(true);
2021-09-22 18:07:13 +02:00
const [isTorDisabled, setIsTorDisabled] = useState(false);
2021-08-24 07:00:57 +02:00
useEffect(() => {
BlueElectrum.isDisabled().then(setIsElectrumDisabled);
2021-09-22 18:07:13 +02:00
isTorDaemonDisabled().then(setIsTorDisabled);
2021-08-24 07:00:57 +02:00
}, []);
2021-09-22 05:55:14 +02:00
useEffect(() => {
2021-09-22 18:07:13 +02:00
setIsTorDaemonDisabled(isTorDisabled);
}, [isTorDisabled]);
2021-09-22 05:55:14 +02:00
2021-01-19 04:40:11 +01:00
const setIsHandOffUseEnabledAsyncStorage = value => {
setIsHandOffUseEnabled(value);
2021-05-18 22:38:18 +02:00
return BlueApp.setIsHandoffEnabled(value);
2021-01-19 04:40:11 +01:00
};
2021-09-07 21:30:07 +02:00
const saveToDisk = async (force = false) => {
if (BlueApp.getWallets().length === 0 && !force) {
console.log('not saving empty wallets array');
return;
}
BlueApp.tx_metadata = txMetadata;
await BlueApp.saveToDisk();
setWallets([...BlueApp.getWallets()]);
txMetadata = BlueApp.tx_metadata;
};
useEffect(() => {
setWallets(BlueApp.getWallets());
}, []);
2021-01-19 04:40:11 +01:00
useEffect(() => {
(async () => {
try {
2021-05-18 22:38:18 +02:00
const enabledHandoff = await BlueApp.isHandoffEnabled();
2021-01-19 04:40:11 +01:00
setIsHandOffUseEnabled(!!enabledHandoff);
} catch (_e) {
setIsHandOffUseEnabledAsyncStorage(false);
setIsHandOffUseEnabled(false);
}
})();
}, []);
const getPreferredCurrency = async () => {
const item = await getPreferredCurrencyAsyncStorage();
_setPreferredFiatCurrency(item);
};
const setPreferredFiatCurrency = () => {
getPreferredCurrency();
};
2020-12-13 10:52:54 +01:00
const getLanguage = async () => {
const item = await getLanguageAsyncStorage();
_setLanguage(item);
};
const setLanguage = () => {
getLanguage();
};
useEffect(() => {
getPreferredCurrency();
2020-12-13 10:52:54 +01:00
getLanguageAsyncStorage();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const resetWallets = () => {
setWallets(BlueApp.getWallets());
};
const setWalletsWithNewOrder = wallets => {
BlueApp.wallets = wallets;
saveToDisk();
};
2021-01-28 01:30:42 +01:00
const refreshAllWalletTransactions = async (lastSnappedTo, showUpdateStatusIndicator = true) => {
let noErr = true;
try {
2021-01-28 01:30:42 +01:00
if (showUpdateStatusIndicator) {
setWalletTransactionUpdateStatus(WalletTransactionsStatus.ALL);
}
await BlueElectrum.waitTillConnected();
const balanceStart = +new Date();
await fetchWalletBalances(lastSnappedTo);
const balanceEnd = +new Date();
console.log('fetch balance took', (balanceEnd - balanceStart) / 1000, 'sec');
const start = +new Date();
await fetchWalletTransactions(lastSnappedTo);
const end = +new Date();
console.log('fetch tx took', (end - start) / 1000, 'sec');
} catch (err) {
noErr = false;
console.warn(err);
2021-01-28 01:30:42 +01:00
} finally {
setWalletTransactionUpdateStatus(WalletTransactionsStatus.NONE);
}
if (noErr) await saveToDisk(); // caching
};
const fetchAndSaveWalletTransactions = async walletID => {
const index = wallets.findIndex(wallet => wallet.getID() === walletID);
let noErr = true;
try {
2021-01-01 20:15:40 +01:00
// 5sec debounce:
2021-01-28 01:30:42 +01:00
setWalletTransactionUpdateStatus(walletID);
2021-01-01 20:15:40 +01:00
if (+new Date() - _lastTimeTriedToRefetchWallet[walletID] < 5000) {
console.log('re-fetch wallet happens too fast; NOP');
return;
}
_lastTimeTriedToRefetchWallet[walletID] = +new Date();
await BlueElectrum.waitTillConnected();
const balanceStart = +new Date();
await fetchWalletBalances(index);
const balanceEnd = +new Date();
console.log('fetch balance took', (balanceEnd - balanceStart) / 1000, 'sec');
const start = +new Date();
await fetchWalletTransactions(index);
const end = +new Date();
console.log('fetch tx took', (end - start) / 1000, 'sec');
} catch (err) {
noErr = false;
console.warn(err);
2021-01-28 01:30:42 +01:00
} finally {
setWalletTransactionUpdateStatus(WalletTransactionsStatus.NONE);
}
if (noErr) await saveToDisk(); // caching
};
const addWallet = wallet => {
BlueApp.wallets.push(wallet);
setWallets([...BlueApp.getWallets()]);
};
const deleteWallet = wallet => {
BlueApp.deleteWallet(wallet);
setWallets([...BlueApp.getWallets()]);
};
const addAndSaveWallet = async w => {
if (wallets.some(i => i.getID() === w.getID())) {
ReactNativeHapticFeedback.trigger('notificationError', { ignoreAndroidSystemSettings: false });
Alert.alert('', 'This wallet has been previously imported.');
return;
}
const emptyWalletLabel = new LegacyWallet().getLabel();
ReactNativeHapticFeedback.trigger('notificationSuccess', { ignoreAndroidSystemSettings: false });
if (w.getLabel() === emptyWalletLabel) w.setLabel(loc.wallets.import_imported + ' ' + w.typeReadable);
w.setUserHasSavedExport(true);
addWallet(w);
await saveToDisk();
A(A.ENUM.CREATED_WALLET);
Alert.alert('', loc.wallets.import_success);
Notifications.majorTomToGroundControl(w.getAllExternalAddresses(), [], []);
// start balance fetching at the background
await w.fetchBalance();
setWallets([...BlueApp.getWallets()]);
};
let txMetadata = BlueApp.tx_metadata || {};
const getTransactions = BlueApp.getTransactions;
const isAdancedModeEnabled = BlueApp.isAdancedModeEnabled;
const fetchWalletBalances = BlueApp.fetchWalletBalances;
const fetchWalletTransactions = BlueApp.fetchWalletTransactions;
const getBalance = BlueApp.getBalance;
const isStorageEncrypted = BlueApp.storageIsEncrypted;
const startAndDecrypt = BlueApp.startAndDecrypt;
const encryptStorage = BlueApp.encryptStorage;
const sleep = BlueApp.sleep;
const setHodlHodlApiKey = BlueApp.setHodlHodlApiKey;
const getHodlHodlApiKey = BlueApp.getHodlHodlApiKey;
const createFakeStorage = BlueApp.createFakeStorage;
const decryptStorage = BlueApp.decryptStorage;
const isPasswordInUse = BlueApp.isPasswordInUse;
const cachedPassword = BlueApp.cachedPassword;
const setIsAdancedModeEnabled = BlueApp.setIsAdancedModeEnabled;
const getHodlHodlSignatureKey = BlueApp.getHodlHodlSignatureKey;
const addHodlHodlContract = BlueApp.addHodlHodlContract;
const getHodlHodlContracts = BlueApp.getHodlHodlContracts;
const setDoNotTrack = BlueApp.setDoNotTrack;
const isDoNotTrackEnabled = BlueApp.isDoNotTrackEnabled;
const getItem = BlueApp.getItem;
const setItem = BlueApp.setItem;
return (
<BlueStorageContext.Provider
value={{
wallets,
setWalletsWithNewOrder,
txMetadata,
saveToDisk,
getTransactions,
selectedWallet,
setSelectedWallet,
addWallet,
deleteWallet,
addAndSaveWallet,
setItem,
getItem,
getHodlHodlContracts,
isAdancedModeEnabled,
fetchWalletBalances,
fetchWalletTransactions,
fetchAndSaveWalletTransactions,
isStorageEncrypted,
getHodlHodlSignatureKey,
encryptStorage,
startAndDecrypt,
cachedPassword,
addHodlHodlContract,
getBalance,
walletsInitialized,
setWalletsInitialized,
refreshAllWalletTransactions,
sleep,
setHodlHodlApiKey,
createFakeStorage,
resetWallets,
getHodlHodlApiKey,
decryptStorage,
isPasswordInUse,
setIsAdancedModeEnabled,
setPreferredFiatCurrency,
preferredFiatCurrency,
2020-12-13 10:52:54 +01:00
setLanguage,
language,
2021-01-19 04:40:11 +01:00
isHandOffUseEnabled,
setIsHandOffUseEnabledAsyncStorage,
2021-01-28 01:30:42 +01:00
walletTransactionUpdateStatus,
setWalletTransactionUpdateStatus,
setDoNotTrack,
isDoNotTrackEnabled,
2021-08-24 07:00:57 +02:00
isElectrumDisabled,
setIsElectrumDisabled,
2021-09-22 18:07:13 +02:00
isTorDisabled,
setIsTorDisabled,
}}
>
{children}
</BlueStorageContext.Provider>
);
};