Reload wallet if backgrounded (#290)
* creating centralized location to handle stale background state * adding global background threashold * creating auth context * disconnecting from liquid node during force auth * reset did get to homepage variable * fix crash if globalContactsInformation.myProfile is not set * resetting custody account settings * clearing keys information on reset * remove roostock swap listener on reset * resetting webview context on stale auth * adding auth reset to spark context * only load user info once per session * only open tables once per session * making sure to recheck login status to fix issue with initial load * adding large heap flag * fixing sql table open bug * making sure didLoadUserSettings runs on app open * fixing unqiueName being null bug * fixing race condition causing switch to naive spark version * misc changes
This commit is contained in:
@@ -114,6 +114,7 @@ import { RootstockSwapProvider } from './context-store/rootstockSwapContext';
|
||||
import { SparkConnectionManager } from './context-store/sparkConnection';
|
||||
import { GlobalNostrWalletConnectProvider } from './context-store/NWC';
|
||||
import { GlobalServerTimeProvider } from './context-store/serverTime';
|
||||
import { AuthStatusProvider } from './context-store/authContext';
|
||||
import { ActiveCustodyAccountProvider } from './context-store/activeAccount';
|
||||
import { GiftProvider } from './context-store/giftContext';
|
||||
// import { LRC20EventProvider } from './context-store/lrc20Listener';
|
||||
@@ -138,51 +139,53 @@ function App(): JSX.Element {
|
||||
<GlobalThemeProvider>
|
||||
<DropdownProvider>
|
||||
<AppStatusProvider>
|
||||
<KeysContextProvider>
|
||||
<GlobalContactsList>
|
||||
<GlobalContextProvider>
|
||||
<ActiveCustodyAccountProvider>
|
||||
<WebViewProvider>
|
||||
{/* <GlobaleCashVariables> */}
|
||||
<SparkWalletProvider>
|
||||
<GLobalNodeContextProider>
|
||||
{/* <GlobalConbinedTxContextProvider> */}
|
||||
<GlobalAppDataProvider>
|
||||
<POSTransactionsProvider>
|
||||
<PushNotificationProvider>
|
||||
<LiquidEventProvider>
|
||||
<RootstockSwapProvider>
|
||||
{/* <LRC20EventProvider> */}
|
||||
<GlobalNostrWalletConnectProvider>
|
||||
{/* <LightningEventProvider> */}
|
||||
<ImageCacheProvider>
|
||||
<GlobalServerTimeProvider>
|
||||
<GiftProvider>
|
||||
{/* <Suspense
|
||||
<AuthStatusProvider>
|
||||
<KeysContextProvider>
|
||||
<GlobalContactsList>
|
||||
<GlobalContextProvider>
|
||||
<ActiveCustodyAccountProvider>
|
||||
<WebViewProvider>
|
||||
{/* <GlobaleCashVariables> */}
|
||||
<SparkWalletProvider>
|
||||
<GLobalNodeContextProider>
|
||||
{/* <GlobalConbinedTxContextProvider> */}
|
||||
<GlobalAppDataProvider>
|
||||
<POSTransactionsProvider>
|
||||
<PushNotificationProvider>
|
||||
<LiquidEventProvider>
|
||||
<RootstockSwapProvider>
|
||||
{/* <LRC20EventProvider> */}
|
||||
<GlobalNostrWalletConnectProvider>
|
||||
{/* <LightningEventProvider> */}
|
||||
<ImageCacheProvider>
|
||||
<GlobalServerTimeProvider>
|
||||
<GiftProvider>
|
||||
{/* <Suspense
|
||||
fallback={<FullLoadingScreen text={'Loading Page'} />}> */}
|
||||
<ResetStack />
|
||||
</GiftProvider>
|
||||
{/* </Suspense> */}
|
||||
</GlobalServerTimeProvider>
|
||||
</ImageCacheProvider>
|
||||
{/* </LightningEventProvider> */}
|
||||
</GlobalNostrWalletConnectProvider>
|
||||
{/* </LRC20EventProvider> */}
|
||||
</RootstockSwapProvider>
|
||||
</LiquidEventProvider>
|
||||
</PushNotificationProvider>
|
||||
</POSTransactionsProvider>
|
||||
</GlobalAppDataProvider>
|
||||
{/* <BreezTest /> */}
|
||||
{/* </GlobalConbinedTxContextProvider> */}
|
||||
</GLobalNodeContextProider>
|
||||
</SparkWalletProvider>
|
||||
{/* </GlobaleCashVariables> */}
|
||||
</WebViewProvider>
|
||||
</ActiveCustodyAccountProvider>
|
||||
</GlobalContextProvider>
|
||||
</GlobalContactsList>
|
||||
</KeysContextProvider>
|
||||
<ResetStack />
|
||||
</GiftProvider>
|
||||
{/* </Suspense> */}
|
||||
</GlobalServerTimeProvider>
|
||||
</ImageCacheProvider>
|
||||
{/* </LightningEventProvider> */}
|
||||
</GlobalNostrWalletConnectProvider>
|
||||
{/* </LRC20EventProvider> */}
|
||||
</RootstockSwapProvider>
|
||||
</LiquidEventProvider>
|
||||
</PushNotificationProvider>
|
||||
</POSTransactionsProvider>
|
||||
</GlobalAppDataProvider>
|
||||
{/* <BreezTest /> */}
|
||||
{/* </GlobalConbinedTxContextProvider> */}
|
||||
</GLobalNodeContextProider>
|
||||
</SparkWalletProvider>
|
||||
{/* </GlobaleCashVariables> */}
|
||||
</WebViewProvider>
|
||||
</ActiveCustodyAccountProvider>
|
||||
</GlobalContextProvider>
|
||||
</GlobalContactsList>
|
||||
</KeysContextProvider>
|
||||
</AuthStatusProvider>
|
||||
</AppStatusProvider>
|
||||
</DropdownProvider>
|
||||
</GlobalThemeProvider>
|
||||
@@ -442,7 +445,6 @@ function ResetStack(): JSX.Element | null {
|
||||
await runSecureStoreMigrationV2();
|
||||
const [
|
||||
initialURL,
|
||||
// registerBackground,
|
||||
loginModeType,
|
||||
pin,
|
||||
mnemonic,
|
||||
@@ -450,7 +452,6 @@ function ResetStack(): JSX.Element | null {
|
||||
userSelectedLanguage,
|
||||
] = await Promise.all([
|
||||
getInitialURL(),
|
||||
// registerBackgroundNotificationTask(),
|
||||
retrieveData(LOGIN_SECURITY_MODE_TYPE_KEY),
|
||||
retrieveData('pinHash'),
|
||||
retrieveData('encryptedMnemonic'),
|
||||
@@ -492,10 +493,32 @@ function ResetStack(): JSX.Element | null {
|
||||
}
|
||||
|
||||
if (appState === 'background') return;
|
||||
if (didInitializeSettings.current) return;
|
||||
didInitializeSettings.current = true;
|
||||
|
||||
initWallet();
|
||||
if (!didInitializeSettings.current) {
|
||||
didInitializeSettings.current = true;
|
||||
initWallet();
|
||||
} else {
|
||||
// Re-check login status when app becomes active again
|
||||
async function recheckLoginStatus() {
|
||||
const [pin, mnemonic, securitySettings] = await Promise.all([
|
||||
retrieveData('pinHash'),
|
||||
retrieveData('encryptedMnemonic'),
|
||||
getLocalStorageItem(LOGIN_SECUITY_MODE_KEY),
|
||||
]);
|
||||
|
||||
const storedSettings = JSON.parse(securitySettings);
|
||||
|
||||
setInitSettings(prev => {
|
||||
return {
|
||||
...prev,
|
||||
isLoggedIn: !!pin.value && !!mnemonic.value,
|
||||
hasSecurityEnabled: storedSettings?.isSecurityEnabled ?? true,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
recheckLoginStatus();
|
||||
}
|
||||
}, [appState]);
|
||||
|
||||
const handleAnimationFinish = () => {
|
||||
|
||||
+17
-11
@@ -94,9 +94,9 @@ android {
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 60
|
||||
versionName "0.7.2"
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86_64', 'x86', 'armeabi-v7a'// Exclude riscv64
|
||||
}
|
||||
// ndk {
|
||||
// abiFilters 'arm64-v8a', 'x86_64', 'x86', 'armeabi-v7a'// Exclude riscv64
|
||||
// }
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
@@ -113,14 +113,14 @@ android {
|
||||
keyPassword System.getenv("MY_KEY_PASSWORD")
|
||||
}
|
||||
}
|
||||
// splits {
|
||||
// abi {
|
||||
// reset()
|
||||
// enable true
|
||||
// universalApk true
|
||||
// include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
// }
|
||||
// }
|
||||
splits {
|
||||
abi {
|
||||
reset()
|
||||
enable true
|
||||
universalApk true
|
||||
include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
@@ -149,6 +149,12 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
useLegacyPackaging true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="${usesCleartextTraffic}"
|
||||
android:supportsRtl="true">
|
||||
android:supportsRtl="true"
|
||||
android:largeHeap="true">
|
||||
|
||||
|
||||
<!-- Firebase notification settings -->
|
||||
|
||||
@@ -194,7 +194,7 @@ export default function AddContactsHalfModal({
|
||||
newContact: {
|
||||
name: searchInput.split('@')[0],
|
||||
bio: '',
|
||||
uniqueName: null,
|
||||
uniqueName: '',
|
||||
isFavorite: false,
|
||||
transactions: [],
|
||||
unlookedTransactions: 0,
|
||||
|
||||
@@ -43,6 +43,7 @@ import {
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useGlobalInsets } from '../../../../../context-store/insetsProvider';
|
||||
import { TAB_ITEM_HEIGHT } from '../../../../../navigation/tabs';
|
||||
import { formatDisplayName } from './utils/formatListDisplayName';
|
||||
|
||||
export default function ContactsPage({ navigation }) {
|
||||
const { contactsPrivateKey, publicKey } = useKeysContext();
|
||||
@@ -66,7 +67,7 @@ export default function ContactsPage({ navigation }) {
|
||||
const tabsNavigate = navigation.navigate;
|
||||
const navigate = useNavigation();
|
||||
const myProfile = globalContactsInformation.myProfile;
|
||||
const didEditProfile = myProfile.didEditProfile;
|
||||
const didEditProfile = myProfile?.didEditProfile;
|
||||
|
||||
// Use custom hooks for processed data
|
||||
const contactInfoList = useProcessedContacts(
|
||||
@@ -524,11 +525,7 @@ const PinnedContactElement = memo(
|
||||
fontSize: SIZES.small,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
content={
|
||||
contact.name?.length
|
||||
? contact.name.trim()
|
||||
: contact.uniqueName.trim()
|
||||
}
|
||||
content={formatDisplayName(contact)}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
@@ -587,9 +584,6 @@ const ContactElement = memo(
|
||||
navigateToExpandedContact(contact);
|
||||
}, [contact, navigateToExpandedContact]);
|
||||
|
||||
const displayName = contact.name?.length
|
||||
? contact.name
|
||||
: contact.uniqueName;
|
||||
const formattedDate = lastUpdated
|
||||
? createFormattedDate(
|
||||
lastUpdated - serverTimeOffset,
|
||||
@@ -618,7 +612,7 @@ const ContactElement = memo(
|
||||
CustomEllipsizeMode="tail"
|
||||
CustomNumberOfLines={1}
|
||||
styles={{ flex: 1, marginRight: 5 }}
|
||||
content={displayName}
|
||||
content={formatDisplayName(contact)}
|
||||
/>
|
||||
{hasUnlookedTransaction && <View style={notificationStyle} />}
|
||||
<ThemeText
|
||||
|
||||
@@ -286,12 +286,26 @@ function InnerContent({
|
||||
selectedAddedContact?.receiveAddress || '';
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
const [inputs, setInputs] = useState({
|
||||
name: '',
|
||||
bio: '',
|
||||
uniquename: '',
|
||||
receiveAddress: '',
|
||||
});
|
||||
const [inputs, setInputs] = useState(() => ({
|
||||
name: isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactName || ''
|
||||
: selectedAddedContactName || ''
|
||||
: '',
|
||||
bio: isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactBio || ''
|
||||
: selectedAddedContactBio || ''
|
||||
: '',
|
||||
uniquename: isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactUniqueName || ''
|
||||
: selectedAddedContactUniqueName || ''
|
||||
: '',
|
||||
receiveAddress: selectedAddedContactReceiveAddress || '',
|
||||
}));
|
||||
|
||||
// Remove the entire useEffect
|
||||
const [tempImage, setTempImage] = useState({
|
||||
uri: null,
|
||||
comparison: null,
|
||||
@@ -310,42 +324,6 @@ function InnerContent({
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
changeInputText(
|
||||
isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactName || ''
|
||||
: selectedAddedContactName || ''
|
||||
: '',
|
||||
'name',
|
||||
);
|
||||
changeInputText(
|
||||
isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactBio || ''
|
||||
: selectedAddedContactBio || ''
|
||||
: '',
|
||||
'bio',
|
||||
);
|
||||
changeInputText(
|
||||
isFirstTimeEditing
|
||||
? isEditingMyProfile
|
||||
? myContactUniqueName || ''
|
||||
: selectedAddedContactUniqueName || ''
|
||||
: '',
|
||||
'uniquename',
|
||||
);
|
||||
changeInputText(selectedAddedContactReceiveAddress || '', 'receiveAddress');
|
||||
}, [
|
||||
isEditingMyProfile,
|
||||
myContactName,
|
||||
myContactBio,
|
||||
myContactUniqueName,
|
||||
selectedAddedContactName,
|
||||
selectedAddedContactBio,
|
||||
selectedAddedContactUniqueName,
|
||||
]);
|
||||
|
||||
const myProfileImage = cache[myContact?.uuid];
|
||||
const selectedAddedContactImage = cache[selectedAddedContact?.uuid];
|
||||
const hasImage = tempImage.shouldDelete
|
||||
@@ -612,6 +590,8 @@ function InnerContent({
|
||||
? inputs.uniquename || myContact.uniqueName
|
||||
: inputs.uniquename;
|
||||
|
||||
console.log(selectedAddedContact, 'tt', isEditingMyProfile);
|
||||
|
||||
if (isEditingMyProfile) {
|
||||
if (
|
||||
myContact?.bio === inputs.bio &&
|
||||
@@ -661,6 +641,7 @@ function InnerContent({
|
||||
navigate.goBack();
|
||||
}
|
||||
} else {
|
||||
console.log(selectedAddedContact, 'testing');
|
||||
if (fromInitialAdd) {
|
||||
let tempContact = JSON.parse(JSON.stringify(selectedAddedContact));
|
||||
tempContact.name = inputs.name.trim();
|
||||
@@ -693,7 +674,7 @@ function InnerContent({
|
||||
} else return addedContact;
|
||||
});
|
||||
} else newAddedContacts.push(tempContact);
|
||||
|
||||
console.log(tempContact, newAddedContacts);
|
||||
toggleGlobalContactsInformation(
|
||||
{
|
||||
myProfile: {
|
||||
@@ -733,6 +714,7 @@ function InnerContent({
|
||||
) {
|
||||
contact['receiveAddress'] = inputs.receiveAddress.trim();
|
||||
}
|
||||
console.log(contact, newAddedContacts);
|
||||
|
||||
toggleGlobalContactsInformation(
|
||||
{
|
||||
|
||||
+5
-4
@@ -30,6 +30,7 @@ import useHandleBackPressNew from '../../../../../hooks/useHandleBackPressNew';
|
||||
import { useImageCache } from '../../../../../../context-store/imageCache';
|
||||
import ContactProfileImage from '../internalComponents/profileImage';
|
||||
import { useGlobalInsets } from '../../../../../../context-store/insetsProvider';
|
||||
import { formatDisplayName } from '../utils/formatListDisplayName';
|
||||
|
||||
export default function ChooseContactHalfModal() {
|
||||
const { theme, darkModeType } = useGlobalThemeContext();
|
||||
@@ -74,7 +75,9 @@ export default function ChooseContactHalfModal() {
|
||||
return (
|
||||
contact.name.toLowerCase().startsWith(inputText.toLowerCase()) ||
|
||||
(!contact.isLNURL &&
|
||||
contact.uniqueName.toLowerCase().startsWith(inputText.toLowerCase()))
|
||||
contact.uniqueName
|
||||
?.toLowerCase()
|
||||
?.startsWith(inputText.toLowerCase()))
|
||||
);
|
||||
});
|
||||
}, [sortedContacts, inputText, cache]);
|
||||
@@ -119,9 +122,7 @@ export default function ChooseContactHalfModal() {
|
||||
<ThemeText
|
||||
CustomEllipsizeMode={'tail'}
|
||||
CustomNumberOfLines={1}
|
||||
content={
|
||||
!!contact.name.length ? contact.name : contact.uniqueName
|
||||
}
|
||||
content={formatDisplayName(contact)}
|
||||
/>
|
||||
<ThemeText
|
||||
CustomEllipsizeMode={'tail'}
|
||||
|
||||
@@ -23,7 +23,7 @@ export default async function getDeepLinkUser({
|
||||
const newContact = {
|
||||
name: user.contacts.myProfile.name || '',
|
||||
bio: user.contacts.myProfile.bio || '',
|
||||
uniqueName: user.contacts.myProfile.uniqueName,
|
||||
uniqueName: user.contacts.myProfile.uniqueName || '',
|
||||
isFavorite: false,
|
||||
unlookedTransactions: 0,
|
||||
uuid: user.contacts.myProfile.uuid,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
export function formatDisplayName(contact) {
|
||||
try {
|
||||
if (contact.name?.length) {
|
||||
return contact.name?.trim();
|
||||
} else if (contact.uniqueName?.length) {
|
||||
return contact.uniqueName?.trim();
|
||||
} else if (contact.isLNURL) {
|
||||
const [prefix, suffix] = contact.receiveAddress.split('@');
|
||||
console.log(prefix, suffix);
|
||||
return prefix;
|
||||
}
|
||||
return '';
|
||||
} catch (err) {
|
||||
console.log('error formatting display name', err);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,8 @@ const IS_DONTATION_PAYMENT_BUFFER = 10_000;
|
||||
const SKELETON_ANIMATION_SPEED = 1200;
|
||||
const TOKEN_TICKER_MAX_LENGTH = 10;
|
||||
|
||||
const BACKGROUND_THRESHOLD_MS = 3 * 60 * 1000;
|
||||
|
||||
const SCREEN_DIMENSIONS = Dimensions.get('screen');
|
||||
|
||||
export {
|
||||
@@ -178,4 +180,5 @@ export {
|
||||
GIFT_DEEPLINK_REGEX,
|
||||
GIFT_DERIVE_PATH_CUTOFF,
|
||||
CONTACT_UNIVERSAL_LINK_REGEX,
|
||||
BACKGROUND_THRESHOLD_MS,
|
||||
};
|
||||
|
||||
@@ -1,18 +1,36 @@
|
||||
import {openDatabaseAsync} from 'expo-sqlite';
|
||||
import { openDatabaseAsync } from 'expo-sqlite';
|
||||
|
||||
export const ROOTSTOCK_DB_NAME = 'ROOTSTOCK_SWAPS';
|
||||
export const ROOTSTOCK_TABLE_NAME = 'saved_rootstock_swaps';
|
||||
let sqlLiteDB;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
if (!sqlLiteDB) {
|
||||
async function openDBConnection() {
|
||||
sqlLiteDB = await openDatabaseAsync(`${ROOTSTOCK_DB_NAME}.db`);
|
||||
async function openDBConnection() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
sqlLiteDB = await openDatabaseAsync(`${ROOTSTOCK_DB_NAME}.db`);
|
||||
isInitialized = true;
|
||||
return sqlLiteDB;
|
||||
})();
|
||||
}
|
||||
openDBConnection();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isRoostockDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
export const ensureRootstockDatabaseReady = async () => {
|
||||
if (!isInitialized) {
|
||||
await openDBConnection();
|
||||
}
|
||||
return sqlLiteDB;
|
||||
};
|
||||
|
||||
export async function initRootstockSwapDB() {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
await sqlLiteDB.execAsync(`PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE IF NOT EXISTS ${ROOTSTOCK_TABLE_NAME} (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
@@ -30,6 +48,7 @@ export async function initRootstockSwapDB() {
|
||||
// Save swap as JSON string
|
||||
export async function saveSwap(id, type, data) {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`INSERT OR REPLACE INTO ${ROOTSTOCK_TABLE_NAME} (id, type, data) VALUES (?, ?, ?)`,
|
||||
[id, type, JSON.stringify(data)],
|
||||
@@ -42,6 +61,7 @@ export async function saveSwap(id, type, data) {
|
||||
// Update swap with new details properties
|
||||
export async function updateSwap(id, newDetails) {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
// First, get the existing swap data
|
||||
const existingSwap = await sqlLiteDB.getFirstAsync(
|
||||
`SELECT data FROM ${ROOTSTOCK_TABLE_NAME} WHERE id = ?`,
|
||||
@@ -78,6 +98,7 @@ export async function updateSwap(id, newDetails) {
|
||||
// Load all swaps
|
||||
export async function loadSwaps() {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${ROOTSTOCK_TABLE_NAME}`,
|
||||
);
|
||||
@@ -94,6 +115,7 @@ export async function loadSwaps() {
|
||||
// Load single swap by id
|
||||
export async function getSwapById(id) {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${ROOTSTOCK_TABLE_NAME} WHERE id = ?`,
|
||||
[id],
|
||||
@@ -114,6 +136,7 @@ export async function getSwapById(id) {
|
||||
*/
|
||||
export async function deleteSwapById(id) {
|
||||
try {
|
||||
await ensureRootstockDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${ROOTSTOCK_TABLE_NAME} WHERE id = ?`,
|
||||
[id],
|
||||
|
||||
@@ -3,30 +3,20 @@ import {
|
||||
defaultConfig,
|
||||
LiquidNetwork,
|
||||
} from '@breeztech/react-native-breez-sdk-liquid';
|
||||
import {getOrCreateDirectory} from './connectToNode';
|
||||
import {crashlyticsLogReport} from './crashlyticsLogs';
|
||||
import { getOrCreateDirectory } from './connectToNode';
|
||||
import { crashlyticsLogReport } from './crashlyticsLogs';
|
||||
|
||||
const logHandler = logEntry => {
|
||||
if (logEntry.level != 'TRACE') {
|
||||
console.log(`[${logEntry.level}]: ${logEntry.line}`);
|
||||
}
|
||||
};
|
||||
let didConnect = false;
|
||||
export default async function connectToLiquidNode(accountMnemoinc) {
|
||||
crashlyticsLogReport('Starting connect to liquid function');
|
||||
// Create the default config
|
||||
|
||||
// setLogger(logHandler);
|
||||
|
||||
if (didConnect) {
|
||||
console.log('RUNNING IN DID CONNECT');
|
||||
return {
|
||||
isConnected: true,
|
||||
reason: null,
|
||||
};
|
||||
}
|
||||
|
||||
didConnect = true;
|
||||
try {
|
||||
crashlyticsLogReport('Getting config and mnemoinc');
|
||||
// Create the default config, providing your Breez API key
|
||||
@@ -53,7 +43,7 @@ export default async function connectToLiquidNode(accountMnemoinc) {
|
||||
// console.log(`Working directory: ${config.workingDir}`);
|
||||
// config.workingDir = "path to writable directory"
|
||||
crashlyticsLogReport('Running connect request');
|
||||
await connect({mnemonic, config});
|
||||
await connect({ mnemonic, config });
|
||||
// addEventListener(breezLiquidEvent);
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,22 +1,39 @@
|
||||
// giftCardStorage.js
|
||||
import {openDatabaseAsync} from 'expo-sqlite';
|
||||
import { openDatabaseAsync } from 'expo-sqlite';
|
||||
import fetchBackend from '../../../db/handleBackend';
|
||||
|
||||
export const GIFT_CARDS_TABLE_NAME = 'giftCardsTable';
|
||||
export const GIFT_CARD_UPDATE_EVENT_NAME = 'GIFT_CARD_UPDATED';
|
||||
|
||||
let giftCardDB;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
// Initialize database connection
|
||||
if (!giftCardDB) {
|
||||
async function openGiftCardDB() {
|
||||
giftCardDB = await openDatabaseAsync('giftCards.db');
|
||||
async function openGiftCardDB() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
giftCardDB = await openDatabaseAsync('giftCards.db');
|
||||
isInitialized = true;
|
||||
return giftCardDB;
|
||||
})();
|
||||
}
|
||||
openGiftCardDB();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isGiftCardDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
export const ensureGiftCardDatabaseReady = async () => {
|
||||
if (!isInitialized) {
|
||||
await openGiftCardDB();
|
||||
}
|
||||
return giftCardDB;
|
||||
};
|
||||
|
||||
export const initializeGiftCardDatabase = async () => {
|
||||
try {
|
||||
await ensureGiftCardDatabaseReady();
|
||||
await giftCardDB.execAsync(`PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE IF NOT EXISTS ${GIFT_CARDS_TABLE_NAME} (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -35,6 +52,7 @@ export const initializeGiftCardDatabase = async () => {
|
||||
|
||||
export const getGiftCardData = async invoice => {
|
||||
try {
|
||||
await ensureGiftCardDatabaseReady();
|
||||
const result = await giftCardDB.getFirstAsync(
|
||||
`SELECT * FROM ${GIFT_CARDS_TABLE_NAME} WHERE invoice = ?;`,
|
||||
[invoice],
|
||||
@@ -57,6 +75,7 @@ export const getGiftCardData = async invoice => {
|
||||
|
||||
export const saveGiftCardData = async (invoice, giftCardData) => {
|
||||
try {
|
||||
await ensureGiftCardDatabaseReady();
|
||||
const existingData = await giftCardDB.getFirstAsync(
|
||||
`SELECT id FROM ${GIFT_CARDS_TABLE_NAME} WHERE invoice = ?;`,
|
||||
[invoice],
|
||||
@@ -156,6 +175,7 @@ export const fetchAndCacheGiftCardData = async (
|
||||
|
||||
export const getAllGiftCards = async () => {
|
||||
try {
|
||||
await ensureGiftCardDatabaseReady();
|
||||
const result = await giftCardDB.getAllAsync(
|
||||
`SELECT * FROM ${GIFT_CARDS_TABLE_NAME} ORDER BY lastUpdated DESC;`,
|
||||
);
|
||||
@@ -174,6 +194,7 @@ export const getAllGiftCards = async () => {
|
||||
|
||||
export const deleteGiftCardData = async invoice => {
|
||||
try {
|
||||
await ensureGiftCardDatabaseReady();
|
||||
await giftCardDB.runAsync(
|
||||
`DELETE FROM ${GIFT_CARDS_TABLE_NAME} WHERE invoice = ?;`,
|
||||
[invoice],
|
||||
|
||||
@@ -4,14 +4,34 @@ export const CACHED_GIFTS = 'SAVED_GIFTS';
|
||||
|
||||
let sqlLiteDB = null;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
const getDatabase = async () => {
|
||||
try {
|
||||
if (!sqlLiteDB) {
|
||||
async function openDBConnection() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
console.log('Opening database connection...');
|
||||
sqlLiteDB = await SQLite.openDatabaseAsync(`${CACHED_GIFTS}.db`);
|
||||
console.log('Database connection opened');
|
||||
}
|
||||
return sqlLiteDB;
|
||||
})();
|
||||
}
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isGiftDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
const ensureGiftDatabaseReady = async () => {
|
||||
if (!sqlLiteDB) {
|
||||
await openDBConnection();
|
||||
}
|
||||
return sqlLiteDB;
|
||||
};
|
||||
|
||||
const getDatabase = async () => {
|
||||
try {
|
||||
await ensureGiftDatabaseReady();
|
||||
|
||||
// Initialize database if not already done
|
||||
if (!isInitialized) {
|
||||
@@ -29,9 +49,7 @@ export const initGiftDb = async () => {
|
||||
try {
|
||||
console.log('Initializing gift database...');
|
||||
|
||||
if (!sqlLiteDB) {
|
||||
sqlLiteDB = await SQLite.openDatabaseAsync(`${CACHED_GIFTS}.db`);
|
||||
}
|
||||
await ensureGiftDatabaseReady();
|
||||
|
||||
await sqlLiteDB.execAsync(`
|
||||
PRAGMA journal_mode = WAL;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { privateKeyFromSeedWords } from './nostrCompatability';
|
||||
import { getPublicKey } from 'nostr-tools';
|
||||
import { addDataToCollection, getDataFromCollection } from '../../db';
|
||||
import { getDataFromCollection } from '../../db';
|
||||
import { generateRandomContact } from './contacts';
|
||||
import {
|
||||
getCurrentDateFormatted,
|
||||
@@ -13,39 +11,26 @@ import {
|
||||
} from '../constants';
|
||||
import { sendDataToDB } from '../../db/interactionManager';
|
||||
import { firebaseAuth, initializeFirebase } from '../../db/initializeFirebase';
|
||||
import {
|
||||
fetchLocalStorageItems,
|
||||
shouldLoadExploreData,
|
||||
} from './initializeUserSettingsHelpers';
|
||||
import { fetchLocalStorageItems } from './initializeUserSettingsHelpers';
|
||||
import { crashlyticsLogReport } from './crashlyticsLogs';
|
||||
import { getLocalStorageItem, setLocalStorageItem } from './localStorage';
|
||||
import fetchBackend from '../../db/handleBackend';
|
||||
import { setLocalStorageItem } from './localStorage';
|
||||
import { getNWCData } from './nwc';
|
||||
import { getNWCSparkIdentityPubKey, initializeNWCWallet } from './nwc/wallet';
|
||||
|
||||
export default async function initializeUserSettingsFromHistory({
|
||||
accountMnemoinc,
|
||||
setContactsPrivateKey,
|
||||
setMasterInfoObject,
|
||||
toggleGlobalContactsInformation,
|
||||
toggleGlobalAppDataInformation,
|
||||
toggleMasterInfoObject,
|
||||
preloadedData,
|
||||
setPreLoadedUserData,
|
||||
privateKey,
|
||||
publicKey,
|
||||
}) {
|
||||
try {
|
||||
crashlyticsLogReport('Begining process of getting user settings');
|
||||
let needsToUpdate = false;
|
||||
let tempObject = {};
|
||||
const mnemonic = accountMnemoinc;
|
||||
|
||||
if (!mnemonic) throw new Error('Unable to load user settings, no mnemonic');
|
||||
|
||||
const privateKey = await privateKeyFromSeedWords(mnemonic);
|
||||
|
||||
const publicKey = privateKey ? getPublicKey(privateKey) : null;
|
||||
|
||||
if (!privateKey || !publicKey) throw Error('Failed to retrieve keys');
|
||||
|
||||
const [
|
||||
_,
|
||||
@@ -110,8 +95,6 @@ export default async function initializeUserSettingsFromHistory({
|
||||
if (blitzStoredData === null) throw Error('Failed to retrive');
|
||||
blitzStoredData = blitzStoredData || {};
|
||||
|
||||
setContactsPrivateKey(privateKey);
|
||||
|
||||
const generatedUniqueName = blitzStoredData?.contacts?.uniqueName
|
||||
? ''
|
||||
: generateRandomContact();
|
||||
|
||||
@@ -15,15 +15,34 @@ export const contactsSQLEventEmitter = new EventEmitter();
|
||||
let sqlLiteDB;
|
||||
let messageQueue = [];
|
||||
let isProcessing = false;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
if (!sqlLiteDB) {
|
||||
async function openDBConnection() {
|
||||
sqlLiteDB = await openDatabaseAsync(`${CACHED_MESSAGES_KEY}.db`);
|
||||
async function openDBConnection() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
sqlLiteDB = await openDatabaseAsync(`${CACHED_MESSAGES_KEY}.db`);
|
||||
isInitialized = true;
|
||||
return sqlLiteDB;
|
||||
})();
|
||||
}
|
||||
openDBConnection();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isMessagesDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
export const ensureDatabaseReady = async () => {
|
||||
if (!isInitialized) {
|
||||
await openDBConnection();
|
||||
}
|
||||
return sqlLiteDB;
|
||||
};
|
||||
|
||||
export const initializeDatabase = async () => {
|
||||
try {
|
||||
await ensureDatabaseReady();
|
||||
await sqlLiteDB.execAsync(`PRAGMA journal_mode = WAL;
|
||||
CREATE TABLE IF NOT EXISTS ${SQL_TABLE_NAME} (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
@@ -35,12 +54,14 @@ export const initializeDatabase = async () => {
|
||||
console.log('didOPEN');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log('error opening messages database', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getCachedMessages = async () => {
|
||||
try {
|
||||
await ensureDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${SQL_TABLE_NAME} ORDER BY timestamp ASC;`,
|
||||
);
|
||||
@@ -143,6 +164,7 @@ const addUnpaidContactTransactions = async ({ newMessagesList, myPubKey }) => {
|
||||
const setCashedMessages = async ({ newMessagesList, myPubKey }) => {
|
||||
const BATCH_SIZE = 25;
|
||||
try {
|
||||
await ensureDatabaseReady();
|
||||
for (let i = 0; i < newMessagesList.length; i += BATCH_SIZE) {
|
||||
const batch = newMessagesList.slice(i, i + BATCH_SIZE);
|
||||
|
||||
@@ -249,6 +271,7 @@ const setCashedMessages = async ({ newMessagesList, myPubKey }) => {
|
||||
|
||||
export const deleteCachedMessages = async contactPubKey => {
|
||||
try {
|
||||
await ensureDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${SQL_TABLE_NAME} WHERE contactPubKey = ?;`,
|
||||
[contactPubKey],
|
||||
@@ -269,6 +292,7 @@ export const deleteCachedMessages = async contactPubKey => {
|
||||
};
|
||||
export const deleteTable = async () => {
|
||||
try {
|
||||
await ensureDatabaseReady();
|
||||
await sqlLiteDB.runAsync(`DROP TABLE IF EXISTS ${SQL_TABLE_NAME};`);
|
||||
console.log(`Table ${SQL_TABLE_NAME} deleted successfully`);
|
||||
} catch (error) {
|
||||
|
||||
+38
-13
@@ -1,9 +1,9 @@
|
||||
import {getLocalStorageItem, setLocalStorageItem} from '../localStorage';
|
||||
import {getTwoWeeksAgoDate} from '../rotateAddressDateChecker';
|
||||
import {decryptMessage} from '../messaging/encodingAndDecodingMessages';
|
||||
import { getLocalStorageItem, setLocalStorageItem } from '../localStorage';
|
||||
import { getTwoWeeksAgoDate } from '../rotateAddressDateChecker';
|
||||
import { decryptMessage } from '../messaging/encodingAndDecodingMessages';
|
||||
import EventEmitter from 'events';
|
||||
import {handleEventEmitterPost} from '../handleEventEmitters';
|
||||
import {openDatabaseAsync} from 'expo-sqlite';
|
||||
import { handleEventEmitterPost } from '../handleEventEmitters';
|
||||
import { openDatabaseAsync } from 'expo-sqlite';
|
||||
export const POS_TRANSACTION_TABLE_NAME = 'POS_TRANSACTIONS';
|
||||
|
||||
export const POS_LAST_RECEIVED_TIME = 'LAST_RECEIVED_POS_EVENT';
|
||||
@@ -14,16 +14,34 @@ export const pointOfSaleEventEmitter = new EventEmitter();
|
||||
let sqlLiteDB;
|
||||
let messageQueue = [];
|
||||
let isProcessing = false;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
if (!sqlLiteDB) {
|
||||
async function openDBConnection() {
|
||||
sqlLiteDB = await openDatabaseAsync(`${POS_TRANSACTION_TABLE_NAME}.db`);
|
||||
async function openDBConnection() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
sqlLiteDB = await openDatabaseAsync(`${POS_TRANSACTION_TABLE_NAME}.db`);
|
||||
isInitialized = true;
|
||||
return sqlLiteDB;
|
||||
})();
|
||||
}
|
||||
openDBConnection();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isSavedPOSTxsDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
export const ensurePOSDatabaseReady = async () => {
|
||||
if (!isInitialized) {
|
||||
await openDBConnection();
|
||||
}
|
||||
return sqlLiteDB;
|
||||
};
|
||||
|
||||
export const initializePOSTransactionsDatabase = async () => {
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
await sqlLiteDB.execAsync('PRAGMA journal_mode = WAL;');
|
||||
|
||||
await sqlLiteDB.execAsync(`
|
||||
@@ -61,7 +79,7 @@ export const initializePOSTransactionsDatabase = async () => {
|
||||
);
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log('error opening pos txs database', err);
|
||||
handleEventEmitterPost(
|
||||
pointOfSaleEventEmitter,
|
||||
DID_OPEN_TABLES_EVENT_NAME,
|
||||
@@ -71,8 +89,10 @@ export const initializePOSTransactionsDatabase = async () => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getSavedPOSTransactions = async () => {
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${POS_TRANSACTION_TABLE_NAME} ORDER BY timestamp DESC;`,
|
||||
);
|
||||
@@ -108,7 +128,7 @@ const processQueue = async () => {
|
||||
if (isProcessing) return;
|
||||
isProcessing = true;
|
||||
while (messageQueue.length > 0) {
|
||||
const {transactionsList, privateKey} = messageQueue.shift();
|
||||
const { transactionsList, privateKey } = messageQueue.shift();
|
||||
try {
|
||||
await setPOSTransactions({
|
||||
transactionsList,
|
||||
@@ -121,7 +141,7 @@ const processQueue = async () => {
|
||||
|
||||
isProcessing = false;
|
||||
};
|
||||
export const queuePOSTransactions = ({transactionsList, privateKey}) => {
|
||||
export const queuePOSTransactions = ({ transactionsList, privateKey }) => {
|
||||
messageQueue.push({
|
||||
transactionsList,
|
||||
privateKey,
|
||||
@@ -131,8 +151,9 @@ export const queuePOSTransactions = ({transactionsList, privateKey}) => {
|
||||
}
|
||||
};
|
||||
|
||||
const setPOSTransactions = async ({transactionsList, privateKey}) => {
|
||||
const setPOSTransactions = async ({ transactionsList, privateKey }) => {
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
// Start a database transaction for better performance
|
||||
await sqlLiteDB.execAsync('BEGIN TRANSACTION;');
|
||||
|
||||
@@ -190,6 +211,7 @@ export const bulkUpdateDidPay = async dbDateAddedArray => {
|
||||
}
|
||||
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
// Generate placeholders for the query (?, ?, ?)
|
||||
const placeholders = dbDateAddedArray.map(() => '?').join(', ');
|
||||
|
||||
@@ -219,6 +241,7 @@ export const updateDidPayForSingleTx = async (didPaySetting, dbDateAdded) => {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`UPDATE ${POS_TRANSACTION_TABLE_NAME}
|
||||
SET didPay = ?
|
||||
@@ -241,6 +264,7 @@ export const updateDidPayForSingleTx = async (didPaySetting, dbDateAdded) => {
|
||||
|
||||
export const deleteEmployee = async employeeName => {
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${POS_TRANSACTION_TABLE_NAME} WHERE LOWER(serverName) = LOWER(?);`,
|
||||
[employeeName],
|
||||
@@ -262,6 +286,7 @@ export const deleteEmployee = async employeeName => {
|
||||
|
||||
export const deletePOSTransactionsTable = async () => {
|
||||
try {
|
||||
await ensurePOSDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DROP TABLE IF EXISTS ${POS_TRANSACTION_TABLE_NAME};`,
|
||||
);
|
||||
|
||||
@@ -1,28 +1,48 @@
|
||||
import EventEmitter from 'events';
|
||||
import { handleEventEmitterPost } from '../handleEventEmitters';
|
||||
import { openDatabaseAsync } from 'expo-sqlite';
|
||||
|
||||
export const SPARK_TRANSACTIONS_DATABASE_NAME = 'SPARK_INFORMATION_DATABASE';
|
||||
export const SPARK_TRANSACTIONS_TABLE_NAME = 'SPARK_TRANSACTIONS';
|
||||
export const LIGHTNING_REQUEST_IDS_TABLE_NAME = 'LIGHTNING_REQUEST_IDS';
|
||||
export const SPARK_REQUEST_IDS_TABLE_NAME = 'SPARK_REQUEST_IDS';
|
||||
export const sparkTransactionsEventEmitter = new EventEmitter();
|
||||
export const SPARK_TX_UPDATE_ENVENT_NAME = 'UPDATE_SPARK_STATE';
|
||||
|
||||
let bulkUpdateTransactionQueue = [];
|
||||
let isProcessingBulkUpdate = false;
|
||||
|
||||
let sqlLiteDB;
|
||||
let isInitialized = false;
|
||||
let initPromise = null;
|
||||
|
||||
if (!sqlLiteDB) {
|
||||
async function openDBConnection() {
|
||||
sqlLiteDB = await openDatabaseAsync(
|
||||
`${SPARK_TRANSACTIONS_DATABASE_NAME}.db`,
|
||||
);
|
||||
async function openDBConnection() {
|
||||
if (!initPromise) {
|
||||
initPromise = (async () => {
|
||||
sqlLiteDB = await openDatabaseAsync(
|
||||
`${SPARK_TRANSACTIONS_DATABASE_NAME}.db`,
|
||||
);
|
||||
isInitialized = true;
|
||||
return sqlLiteDB;
|
||||
})();
|
||||
}
|
||||
openDBConnection();
|
||||
return initPromise;
|
||||
}
|
||||
|
||||
export const isSparkTxDatabaseOpen = () => {
|
||||
return isInitialized;
|
||||
};
|
||||
|
||||
export const ensureSparkDatabaseReady = async () => {
|
||||
if (!isInitialized) {
|
||||
await openDBConnection();
|
||||
}
|
||||
return sqlLiteDB;
|
||||
};
|
||||
|
||||
export const initializeSparkDatabase = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
// Payment status: pending, completed, failed
|
||||
await sqlLiteDB.execAsync(`
|
||||
PRAGMA journal_mode = WAL;
|
||||
@@ -58,13 +78,13 @@ export const initializeSparkDatabase = async () => {
|
||||
console.log('Opened spark transaction and contacts tables');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log('Database initialization failed:', err);
|
||||
console.log('Spark Database initialization failed:', err);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getAllSparkTransactions = async (options = {}) => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const {
|
||||
limit = null,
|
||||
offset = null,
|
||||
@@ -110,6 +130,7 @@ export const getAllSparkTransactions = async (options = {}) => {
|
||||
|
||||
export const getAllPendingSparkPayments = async accountId => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
let query = `
|
||||
SELECT *
|
||||
FROM ${SPARK_TRANSACTIONS_TABLE_NAME}
|
||||
@@ -132,6 +153,7 @@ export const getAllPendingSparkPayments = async accountId => {
|
||||
|
||||
export const getAllSparkContactInvoices = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${SPARK_REQUEST_IDS_TABLE_NAME}`,
|
||||
);
|
||||
@@ -148,6 +170,7 @@ export const addSingleUnpaidSparkTransaction = async tx => {
|
||||
}
|
||||
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`INSERT INTO ${SPARK_REQUEST_IDS_TABLE_NAME}
|
||||
(sparkID, description, sendersPubkey, details)
|
||||
@@ -176,6 +199,7 @@ export const addBulkUnpaidSparkContactTransactions = async transactions => {
|
||||
}
|
||||
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const placeholders = validTransactions.map(() => '(?, ?, ?, ?)').join(', ');
|
||||
|
||||
const values = validTransactions.flatMap(tx => [
|
||||
@@ -208,6 +232,7 @@ export const addBulkUnpaidSparkContactTransactions = async transactions => {
|
||||
|
||||
export const deleteSparkContactTransaction = async sparkID => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${SPARK_REQUEST_IDS_TABLE_NAME} WHERE sparkID = ?`,
|
||||
sparkID,
|
||||
@@ -222,6 +247,7 @@ export const deleteSparkContactTransaction = async sparkID => {
|
||||
|
||||
export const getAllUnpaidSparkLightningInvoices = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const result = await sqlLiteDB.getAllAsync(
|
||||
`SELECT * FROM ${LIGHTNING_REQUEST_IDS_TABLE_NAME}`,
|
||||
);
|
||||
@@ -237,6 +263,7 @@ export const addSingleUnpaidSparkLightningTransaction = async tx => {
|
||||
}
|
||||
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`INSERT INTO ${LIGHTNING_REQUEST_IDS_TABLE_NAME}
|
||||
(sparkID, amount, expiration, description, shouldNavigate, details)
|
||||
@@ -298,6 +325,7 @@ export const bulkUpdateSparkTransactions = async (transactions, ...data) => {
|
||||
|
||||
return addToBulkUpdateQueue(async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
console.log('Running bulk updates', updateType);
|
||||
console.log(transactions);
|
||||
|
||||
@@ -558,6 +586,7 @@ export const addSingleSparkTransaction = async tx => {
|
||||
}
|
||||
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const newDetails = tx.details;
|
||||
await sqlLiteDB.runAsync(
|
||||
`INSERT INTO ${SPARK_TRANSACTIONS_TABLE_NAME}
|
||||
@@ -588,6 +617,7 @@ export const addSingleSparkTransaction = async tx => {
|
||||
|
||||
export const deleteSparkTransaction = async sparkID => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${SPARK_TRANSACTIONS_TABLE_NAME} WHERE sparkID = ?`,
|
||||
sparkID,
|
||||
@@ -605,8 +635,10 @@ export const deleteSparkTransaction = async sparkID => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteUnpaidSparkLightningTransaction = async sparkID => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.runAsync(
|
||||
`DELETE FROM ${LIGHTNING_REQUEST_IDS_TABLE_NAME} WHERE sparkID = ?`,
|
||||
sparkID,
|
||||
@@ -620,6 +652,7 @@ export const deleteUnpaidSparkLightningTransaction = async sparkID => {
|
||||
|
||||
export const deleteSparkTransactionTable = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.execAsync(
|
||||
`DROP TABLE IF EXISTS ${SPARK_TRANSACTIONS_TABLE_NAME}`,
|
||||
);
|
||||
@@ -632,6 +665,7 @@ export const deleteSparkTransactionTable = async () => {
|
||||
|
||||
export const deleteSparkContactsTransactionsTable = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.execAsync(
|
||||
`DROP TABLE IF EXISTS ${SPARK_REQUEST_IDS_TABLE_NAME}`,
|
||||
);
|
||||
@@ -644,6 +678,7 @@ export const deleteSparkContactsTransactionsTable = async () => {
|
||||
|
||||
export const deleteUnpaidSparkLightningTransactionTable = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
await sqlLiteDB.execAsync(
|
||||
`DROP TABLE IF EXISTS ${LIGHTNING_REQUEST_IDS_TABLE_NAME}`,
|
||||
);
|
||||
@@ -656,6 +691,7 @@ export const deleteUnpaidSparkLightningTransactionTable = async () => {
|
||||
|
||||
export const cleanStalePendingSparkLightningTransactions = async () => {
|
||||
try {
|
||||
await ensureSparkDatabaseReady();
|
||||
const now = new Date().getTime();
|
||||
// Delete where status is 'INVOICE_CREATED' and expires_at_time is not null and in the past
|
||||
await sqlLiteDB.runAsync(
|
||||
|
||||
@@ -21,6 +21,8 @@ import { updateMascatWalkingAnimation } from '../../functions/lottieViewColorTra
|
||||
import { crashlyticsLogReport } from '../../functions/crashlyticsLogs';
|
||||
import { useSparkWallet } from '../../../context-store/sparkContext';
|
||||
import { removeLocalStorageItem } from '../../functions/localStorage';
|
||||
import { privateKeyFromSeedWords } from '../../functions/nostrCompatability';
|
||||
import { getPublicKey } from 'nostr-tools';
|
||||
// import { initializeSparkDatabase } from '../../functions/spark/transactions';
|
||||
// import { getCachedSparkTransactions } from '../../functions/spark';
|
||||
// import { getLocalStorageItem, setLocalStorageItem } from '../../functions';
|
||||
@@ -39,7 +41,7 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
const navigate = useNavigation();
|
||||
const {
|
||||
toggleMasterInfoObject,
|
||||
// masterInfoObject,
|
||||
masterInfoObject,
|
||||
setMasterInfoObject,
|
||||
preloadedUserData,
|
||||
setPreLoadedUserData,
|
||||
@@ -106,46 +108,62 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
console.log('Process 1', new Date().getTime());
|
||||
connectToSparkWallet();
|
||||
|
||||
// connectToLiquidNode(accountMnemoinc);
|
||||
const [
|
||||
// didOpen,
|
||||
// giftCardTable,
|
||||
// posTransactions,
|
||||
// sparkTxs,
|
||||
// rootstockSwaps,
|
||||
didLoadUserSettings,
|
||||
] = await Promise.all([
|
||||
// initializeDatabase(),
|
||||
// initializeGiftCardDatabase(),
|
||||
// initializePOSTransactionsDatabase(),
|
||||
// initializeSparkDatabase(),
|
||||
// initRootstockSwapDB(),
|
||||
initializeUserSettingsFromHistory({
|
||||
accountMnemoinc,
|
||||
setContactsPrivateKey: toggleContactsPrivateKey,
|
||||
setMasterInfoObject,
|
||||
toggleGlobalContactsInformation,
|
||||
// toggleGLobalEcashInformation,
|
||||
toggleGlobalAppDataInformation,
|
||||
toggleMasterInfoObject,
|
||||
preloadedData: preloadedUserData.data,
|
||||
setPreLoadedUserData,
|
||||
}),
|
||||
]);
|
||||
const privateKey = await privateKeyFromSeedWords(accountMnemoinc);
|
||||
const publicKey = privateKey ? getPublicKey(privateKey) : null;
|
||||
|
||||
console.log('Process 2', new Date().getTime());
|
||||
crashlyticsLogReport('Opened all SQL lite tables');
|
||||
|
||||
if (!didLoadUserSettings)
|
||||
if (!privateKey || !publicKey)
|
||||
throw new Error(
|
||||
t('screens.inAccount.loadingScreen.userSettingsError'),
|
||||
);
|
||||
crashlyticsLogReport('Loaded users settings from firebase');
|
||||
|
||||
const hasSavedInfo = Object.keys(masterInfoObject || {}).length > 5; //arbitrary number but filters out onboarding items
|
||||
|
||||
if (!hasSavedInfo) {
|
||||
// connectToLiquidNode(accountMnemoinc);
|
||||
const [
|
||||
// didOpen,
|
||||
// giftCardTable,
|
||||
// posTransactions,
|
||||
// sparkTxs,
|
||||
// rootstockSwaps,
|
||||
didLoadUserSettings,
|
||||
] = await Promise.all([
|
||||
// initializeDatabase(),
|
||||
// initializeGiftCardDatabase(),
|
||||
// initializePOSTransactionsDatabase(),
|
||||
// initializeSparkDatabase(),
|
||||
// initRootstockSwapDB(),
|
||||
initializeUserSettingsFromHistory({
|
||||
setMasterInfoObject,
|
||||
toggleGlobalContactsInformation,
|
||||
// toggleGLobalEcashInformation,
|
||||
toggleGlobalAppDataInformation,
|
||||
toggleMasterInfoObject,
|
||||
preloadedData: preloadedUserData.data,
|
||||
setPreLoadedUserData,
|
||||
privateKey,
|
||||
publicKey,
|
||||
}),
|
||||
]);
|
||||
|
||||
console.log('Process 2', new Date().getTime());
|
||||
crashlyticsLogReport('Opened all SQL lite tables');
|
||||
|
||||
if (!didLoadUserSettings)
|
||||
throw new Error(
|
||||
t('screens.inAccount.loadingScreen.userSettingsError'),
|
||||
);
|
||||
crashlyticsLogReport('Loaded users settings from firebase');
|
||||
}
|
||||
|
||||
toggleContactsPrivateKey(privateKey);
|
||||
console.log('Process 3', new Date().getTime());
|
||||
|
||||
const elapsedTime = Date.now() - startTime;
|
||||
const remainingTime = Math.max(0, 1500 - elapsedTime);
|
||||
const remainingTime = Math.max(
|
||||
0,
|
||||
(hasSavedInfo ? 500 : 1500) - elapsedTime,
|
||||
);
|
||||
|
||||
if (remainingTime > 0) {
|
||||
console.log(
|
||||
@@ -165,7 +183,7 @@ export default function ConnectingToNodeLoadingScreen({
|
||||
didRunConnectionRef.current = true;
|
||||
|
||||
requestAnimationFrame(startConnectProcess);
|
||||
}, [preloadedUserData]);
|
||||
}, [preloadedUserData, masterInfoObject]);
|
||||
// useEffect(() => {
|
||||
// if (
|
||||
// Object.keys(masterInfoObject).length === 0 ||
|
||||
|
||||
+48
-30
@@ -12,18 +12,33 @@ import {
|
||||
applyErrorAnimationTheme,
|
||||
updateBlitzAnimationData,
|
||||
} from '../functions/lottieViewColorTransformer';
|
||||
import { initializeDatabase } from '../functions/messaging/cachedMessages';
|
||||
import { initializeGiftCardDatabase } from '../functions/contacts/giftCardStorage';
|
||||
import { initializePOSTransactionsDatabase } from '../functions/pos';
|
||||
import { initializeSparkDatabase } from '../functions/spark/transactions';
|
||||
import { initRootstockSwapDB } from '../functions/boltz/rootstock/swapDb';
|
||||
import {
|
||||
initializeDatabase,
|
||||
isMessagesDatabaseOpen,
|
||||
} from '../functions/messaging/cachedMessages';
|
||||
import {
|
||||
initializeGiftCardDatabase,
|
||||
isGiftCardDatabaseOpen,
|
||||
} from '../functions/contacts/giftCardStorage';
|
||||
import {
|
||||
initializePOSTransactionsDatabase,
|
||||
isSavedPOSTxsDatabaseOpen,
|
||||
} from '../functions/pos';
|
||||
import {
|
||||
initializeSparkDatabase,
|
||||
isSparkTxDatabaseOpen,
|
||||
} from '../functions/spark/transactions';
|
||||
import {
|
||||
initRootstockSwapDB,
|
||||
isRoostockDatabaseOpen,
|
||||
} from '../functions/boltz/rootstock/swapDb';
|
||||
import { GlobalThemeView, ThemeText } from '../functions/CustomElements';
|
||||
import { t } from 'i18next';
|
||||
import CustomButton from '../functions/CustomElements/button';
|
||||
import { INSET_WINDOW_WIDTH } from '../constants/theme';
|
||||
import openWebBrowser from '../functions/openWebBrowser';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
import { initGiftDb } from '../functions/gift/giftsStorage';
|
||||
import { initGiftDb, isGiftDatabaseOpen } from '../functions/gift/giftsStorage';
|
||||
|
||||
import * as ExpoSplashScreen from 'expo-splash-screen';
|
||||
const BlitzAnimation = require('../assets/BlitzAnimation.json');
|
||||
@@ -76,31 +91,34 @@ const SplashScreen = () => {
|
||||
animationRef.current?.play();
|
||||
}, 500);
|
||||
|
||||
const [
|
||||
didOpen,
|
||||
giftCardTable,
|
||||
posTransactions,
|
||||
sparkTxs,
|
||||
rootstockSwaps,
|
||||
giftsDb,
|
||||
] = await Promise.all([
|
||||
initializeDatabase(),
|
||||
initializeGiftCardDatabase(),
|
||||
initializePOSTransactionsDatabase(),
|
||||
initializeSparkDatabase(),
|
||||
initRootstockSwapDB(),
|
||||
initGiftDb(),
|
||||
]);
|
||||
|
||||
if (
|
||||
!didOpen ||
|
||||
!giftCardTable ||
|
||||
!posTransactions ||
|
||||
!sparkTxs ||
|
||||
!rootstockSwaps ||
|
||||
!giftsDb
|
||||
)
|
||||
throw new Error(t('screens.inAccount.loadingScreen.dbInitError'));
|
||||
isMessagesDatabaseOpen() &&
|
||||
isGiftCardDatabaseOpen() &&
|
||||
isSavedPOSTxsDatabaseOpen() &&
|
||||
isSparkTxDatabaseOpen() &&
|
||||
isRoostockDatabaseOpen() &&
|
||||
isGiftDatabaseOpen()
|
||||
) {
|
||||
console.log('Tables are already opened, blocking...');
|
||||
} else {
|
||||
// Initialize databases one at a time
|
||||
const didOpen = await initializeDatabase();
|
||||
const giftCardTable = await initializeGiftCardDatabase();
|
||||
const posTransactions = await initializePOSTransactionsDatabase();
|
||||
const sparkTxs = await initializeSparkDatabase();
|
||||
const rootstockSwaps = await initRootstockSwapDB();
|
||||
const giftsDb = await initGiftDb();
|
||||
|
||||
if (
|
||||
!didOpen ||
|
||||
!giftCardTable ||
|
||||
!posTransactions ||
|
||||
!sparkTxs ||
|
||||
!rootstockSwaps ||
|
||||
!giftsDb
|
||||
)
|
||||
throw new Error(t('screens.inAccount.loadingScreen.dbInitError'));
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (navigate) {
|
||||
|
||||
@@ -14,25 +14,28 @@ import {
|
||||
CUSTODY_ACCOUNTS_STORAGE_KEY,
|
||||
NWC_SECURE_STORE_MNEMOINC,
|
||||
} from '../app/constants';
|
||||
import {useKeysContext} from './keys';
|
||||
import { useKeysContext } from './keys';
|
||||
import {
|
||||
decryptMnemonic,
|
||||
encryptMnemonic,
|
||||
} from '../app/functions/handleMnemonic';
|
||||
import {useGlobalContextProvider} from './context';
|
||||
import { useGlobalContextProvider } from './context';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
// Create a context for the WebView ref
|
||||
const ActiveCustodyAccount = createContext(null);
|
||||
|
||||
export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
const {masterInfoObject} = useGlobalContextProvider();
|
||||
export const ActiveCustodyAccountProvider = ({ children }) => {
|
||||
const { masterInfoObject } = useGlobalContextProvider();
|
||||
const { authResetkey } = useAuthContext();
|
||||
const [custodyAccounts, setCustodyAccounts] = useState([]);
|
||||
const [isUsingNostr, setIsUsingNostr] = useState(false);
|
||||
const {accountMnemoinc} = useKeysContext();
|
||||
const { accountMnemoinc } = useKeysContext();
|
||||
const [nostrSeed, setNostrSeed] = useState('');
|
||||
const hasSessionReset = useRef(false);
|
||||
const selectedAltAccount = custodyAccounts.filter(item => item.isActive);
|
||||
const didSelectAltAccount = !!selectedAltAccount.length;
|
||||
const isInitialRender = useRef(true);
|
||||
const enabledNWC = masterInfoObject.didViewNWCMessage;
|
||||
|
||||
useEffect(() => {
|
||||
@@ -125,10 +128,10 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
JSON.stringify(encriptAccountsList(newAccounts)),
|
||||
);
|
||||
setCustodyAccounts(newAccounts);
|
||||
return {didWork: true};
|
||||
return { didWork: true };
|
||||
} catch (err) {
|
||||
console.log('Remove account error', err);
|
||||
return {didWork: false, err: err.message};
|
||||
return { didWork: false, err: err.message };
|
||||
}
|
||||
};
|
||||
const createAccount = async accountInformation => {
|
||||
@@ -143,10 +146,10 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
JSON.stringify(encriptAccountsList(savedAccountInformation)),
|
||||
);
|
||||
setCustodyAccounts(savedAccountInformation);
|
||||
return {didWork: true};
|
||||
return { didWork: true };
|
||||
} catch (err) {
|
||||
console.log('Create custody account error', err);
|
||||
return {didWork: false, err: err.message};
|
||||
return { didWork: false, err: err.message };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -155,7 +158,7 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
let accountInformation = JSON.parse(JSON.stringify(custodyAccounts));
|
||||
let newAccounts = accountInformation.map(accounts => {
|
||||
if (account.uuid === accounts.uuid) {
|
||||
return {...accounts, ...account};
|
||||
return { ...accounts, ...account };
|
||||
} else return accounts;
|
||||
});
|
||||
|
||||
@@ -164,10 +167,10 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
JSON.stringify(encriptAccountsList(newAccounts)),
|
||||
);
|
||||
setCustodyAccounts(newAccounts);
|
||||
return {didWork: true};
|
||||
return { didWork: true };
|
||||
} catch (err) {
|
||||
console.log('Remove account error', err);
|
||||
return {didWork: false, err: err.message};
|
||||
return { didWork: false, err: err.message };
|
||||
}
|
||||
};
|
||||
const updateAccountCacheOnly = async account => {
|
||||
@@ -176,18 +179,29 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
let accountInformation = JSON.parse(JSON.stringify(custodyAccounts));
|
||||
let newAccounts = accountInformation.map(accounts => {
|
||||
if (account.uuid === accounts.uuid) {
|
||||
return {...accounts, ...account};
|
||||
} else return {...accounts, isActive: false};
|
||||
return { ...accounts, ...account };
|
||||
} else return { ...accounts, isActive: false };
|
||||
});
|
||||
|
||||
setCustodyAccounts(newAccounts);
|
||||
return {didWork: true};
|
||||
return { didWork: true };
|
||||
} catch (err) {
|
||||
console.log('Remove account error', err);
|
||||
return {didWork: false, err: err.message};
|
||||
return { didWork: false, err: err.message };
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
setNostrSeed('');
|
||||
setIsUsingNostr(false);
|
||||
setCustodyAccounts([]);
|
||||
hasSessionReset.current = false;
|
||||
}, [authResetkey]);
|
||||
|
||||
const currentWalletMnemoinc = useMemo(() => {
|
||||
if (didSelectAltAccount) {
|
||||
return selectedAltAccount[0].mnemoinc;
|
||||
@@ -220,7 +234,8 @@ export const ActiveCustodyAccountProvider = ({children}) => {
|
||||
toggleIsUsingNostr,
|
||||
isUsingNostr,
|
||||
nostrSeed,
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ActiveCustodyAccount.Provider>
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { AppState, Dimensions, Platform } from 'react-native';
|
||||
import { getBoltzSwapPairInformation } from '../app/functions/boltz/boltzSwapInfo';
|
||||
import * as Network from 'expo-network';
|
||||
import { navigationRef } from '../navigation/navigationService';
|
||||
import { BACKGROUND_THRESHOLD_MS } from '../app/constants';
|
||||
|
||||
// Initiate context
|
||||
const AppStatusManager = createContext(null);
|
||||
@@ -31,6 +32,8 @@ const AppStatusProvider = ({ children }) => {
|
||||
const [screenDimensions, setScreenDimensions] = useState(() =>
|
||||
Dimensions.get('screen'),
|
||||
);
|
||||
const shouldResetStateRef = useRef(null);
|
||||
const timeInBackgroundRef = useRef(0);
|
||||
|
||||
const hasInitializedNavListener = useRef(false);
|
||||
const hasInitializedBoltzData = useRef(false);
|
||||
@@ -56,6 +59,26 @@ const AppStatusProvider = ({ children }) => {
|
||||
useEffect(() => {
|
||||
const handleAppStateChange = nextAppState => {
|
||||
console.log('App state changed to:', nextAppState);
|
||||
if (nextAppState === 'background') {
|
||||
shouldResetStateRef.current = false;
|
||||
timeInBackgroundRef.current = Date.now();
|
||||
} else if (nextAppState === 'active') {
|
||||
const timeInBackground = timeInBackgroundRef.current
|
||||
? Date.now() - timeInBackgroundRef.current
|
||||
: 0;
|
||||
|
||||
if (timeInBackground > BACKGROUND_THRESHOLD_MS) {
|
||||
setTimeout(() => {
|
||||
toggleDidGetToHomepage(false);
|
||||
}, 100);
|
||||
|
||||
shouldResetStateRef.current = true;
|
||||
} else {
|
||||
shouldResetStateRef.current = false;
|
||||
}
|
||||
timeInBackgroundRef.current = null;
|
||||
}
|
||||
|
||||
setAppState(nextAppState);
|
||||
};
|
||||
|
||||
@@ -187,6 +210,7 @@ const AppStatusProvider = ({ children }) => {
|
||||
toggleDidGetToHomepage,
|
||||
appState,
|
||||
screenDimensions,
|
||||
shouldResetStateRef,
|
||||
}),
|
||||
[
|
||||
minMaxLiquidSwapAmounts,
|
||||
@@ -196,6 +220,7 @@ const AppStatusProvider = ({ children }) => {
|
||||
toggleDidGetToHomepage,
|
||||
appState,
|
||||
screenDimensions,
|
||||
shouldResetStateRef,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { createContext, useState, useContext, useEffect, useMemo } from 'react';
|
||||
import { navigationRef } from '../navigation/navigationService';
|
||||
import { useAppStatus } from './appStatus';
|
||||
|
||||
// Initiate context
|
||||
const AuthStatusManager = createContext(null);
|
||||
|
||||
const AuthStatusProvider = ({ children }) => {
|
||||
const { appState, shouldResetStateRef } = useAppStatus();
|
||||
const [authResetkey, setAuthResetKey] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'active' && shouldResetStateRef.current) {
|
||||
setAuthResetKey(prev => prev + 1);
|
||||
navigationRef.current.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Splash' }],
|
||||
});
|
||||
}
|
||||
}, [appState]);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
authResetkey,
|
||||
}),
|
||||
[authResetkey],
|
||||
);
|
||||
|
||||
return (
|
||||
<AuthStatusManager.Provider value={contextValue}>
|
||||
{children}
|
||||
</AuthStatusManager.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
function useAuthContext() {
|
||||
const context = useContext(AuthStatusManager);
|
||||
if (!context) {
|
||||
throw new Error('useAuthContext must be used within a AuthContextProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
export { AuthStatusManager, AuthStatusProvider, useAuthContext };
|
||||
@@ -237,7 +237,7 @@ export const GlobalContactsList = ({ children }) => {
|
||||
bio: contact.bio,
|
||||
unlookedTransactions: 0,
|
||||
isLNURL: contact.isLNURL,
|
||||
uniqueName: contact.uniqueName,
|
||||
uniqueName: contact.uniqueName || '',
|
||||
uuid: contact.uuid,
|
||||
isAdded: true,
|
||||
isFavorite: false,
|
||||
|
||||
+16
-3
@@ -1,4 +1,4 @@
|
||||
import {getPublicKey} from 'nostr-tools';
|
||||
import { getPublicKey } from 'nostr-tools';
|
||||
import {
|
||||
createContext,
|
||||
useState,
|
||||
@@ -6,22 +6,35 @@ import {
|
||||
useEffect,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { useAuthContext } from './authContext';
|
||||
// Initiate context
|
||||
const KeysContextManager = createContext(null);
|
||||
|
||||
const KeysContextProvider = ({children}) => {
|
||||
const KeysContextProvider = ({ children }) => {
|
||||
const { authResetkey } = useAuthContext();
|
||||
const [contactsPrivateKey, setContactsPrivateKey] = useState('');
|
||||
const publicKey = useMemo(
|
||||
() => (contactsPrivateKey ? getPublicKey(contactsPrivateKey) : null),
|
||||
[contactsPrivateKey],
|
||||
);
|
||||
const [accountMnemoinc, setAccountMnemonic] = useState('');
|
||||
const isInitialRender = useRef(true);
|
||||
|
||||
const toggleContactsPrivateKey = useCallback(newKey => {
|
||||
setContactsPrivateKey(newKey);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
setContactsPrivateKey('');
|
||||
setAccountMnemonic('');
|
||||
}, [authResetkey]);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
contactsPrivateKey,
|
||||
@@ -54,4 +67,4 @@ function useKeysContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
export {KeysContextManager, KeysContextProvider, useKeysContext};
|
||||
export { KeysContextManager, KeysContextProvider, useKeysContext };
|
||||
|
||||
@@ -10,9 +10,11 @@ import {
|
||||
addEventListener,
|
||||
removeEventListener,
|
||||
SdkEventVariant,
|
||||
disconnect,
|
||||
} from '@breeztech/react-native-breez-sdk-liquid';
|
||||
import startLiquidUpdateInterval from '../app/functions/liquidBackupUpdate';
|
||||
import { useNodeContext } from './nodeContext';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
const LiquidEventContext = createContext(null);
|
||||
|
||||
@@ -22,6 +24,7 @@ const REQUIRED_SYNC_COUNT = 2;
|
||||
|
||||
// Create a context for the WebView ref
|
||||
export function LiquidEventProvider({ children }) {
|
||||
const { authResetkey } = useAuthContext();
|
||||
const { toggleLiquidNodeInformation, liquidNodeInformation } =
|
||||
useNodeContext();
|
||||
const initialLiquidRun = useRef(null);
|
||||
@@ -31,6 +34,7 @@ export function LiquidEventProvider({ children }) {
|
||||
const intervalId = useRef(null);
|
||||
const debounceTimer = useRef(null);
|
||||
const syncRunCounter = useRef(0);
|
||||
const isInitialRender = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (!liquidNodeInformation.didConnectToNode) return;
|
||||
@@ -39,6 +43,23 @@ export function LiquidEventProvider({ children }) {
|
||||
startLiquidEventListener(6);
|
||||
}, [liquidNodeInformation.didConnectToNode]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
cleanup();
|
||||
disconnect();
|
||||
toggleLiquidNodeInformation({
|
||||
didConnectToNode: null,
|
||||
transactions: [],
|
||||
userBalance: 0,
|
||||
});
|
||||
liquidEventRunCounter.current = 0;
|
||||
numberOfLiquidEvents.current = DEFAULT_EVENT_LIMIT;
|
||||
initialLiquidRun.current = null;
|
||||
}, [authResetkey]);
|
||||
|
||||
const cleanup = useCallback(() => {
|
||||
if (debounceTimer.current) {
|
||||
clearTimeout(debounceTimer.current);
|
||||
|
||||
@@ -15,6 +15,7 @@ import connectToLiquidNode from '../app/functions/connectToLiquid';
|
||||
import { useSparkWallet } from './sparkContext';
|
||||
import { useGlobalContacts } from './globalContacts';
|
||||
import liquidToSparkSwap from '../app/functions/spark/liquidToSparkSwap';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
// Initiate context
|
||||
const NodeContextManager = createContext(null);
|
||||
@@ -30,6 +31,8 @@ const GLobalNodeContextProider = ({ children }) => {
|
||||
transactions: [],
|
||||
userBalance: 0,
|
||||
});
|
||||
const isInitialRender = useRef(true);
|
||||
const { authResetkey } = useAuthContext();
|
||||
const selectedCurrency = masterInfoObject.fiatCurrency;
|
||||
const [fiatStats, setFiatStats] = useState({ coin: 'USD', value: 100_000 });
|
||||
|
||||
@@ -124,6 +127,14 @@ const GLobalNodeContextProider = ({ children }) => {
|
||||
globalContactsInformation?.myProfile?.uniqueName,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
didRunLiquidConnection.current = false;
|
||||
}, [authResetkey]);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({
|
||||
liquidNodeInformation,
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
useMemo,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import {useKeysContext} from './keys';
|
||||
import {db} from '../db/initializeFirebase';
|
||||
import { useKeysContext } from './keys';
|
||||
import { db } from '../db/initializeFirebase';
|
||||
import {
|
||||
DID_OPEN_TABLES_EVENT_NAME,
|
||||
getSavedPOSTransactions,
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
POS_EVENT_UPDATE,
|
||||
queuePOSTransactions,
|
||||
} from '../app/functions/pos';
|
||||
import {getTwoWeeksAgoDate} from '../app/functions/rotateAddressDateChecker';
|
||||
import { getTwoWeeksAgoDate } from '../app/functions/rotateAddressDateChecker';
|
||||
import {
|
||||
collection,
|
||||
getDocs,
|
||||
@@ -28,8 +28,8 @@ import {
|
||||
// Initiate context
|
||||
const POSTransactionsContextManager = createContext(null);
|
||||
|
||||
const POSTransactionsProvider = ({children}) => {
|
||||
const {publicKey, contactsPrivateKey} = useKeysContext();
|
||||
const POSTransactionsProvider = ({ children }) => {
|
||||
const { publicKey, contactsPrivateKey } = useKeysContext();
|
||||
const [txList, setTxList] = useState([]);
|
||||
const [didOpenTable, setDidOpenTable] = useState(false);
|
||||
|
||||
@@ -165,6 +165,7 @@ const POSTransactionsProvider = ({children}) => {
|
||||
pointOfSaleEventEmitter.on(POS_EVENT_UPDATE, updateTxListFunction);
|
||||
return () => {
|
||||
pointOfSaleEventEmitter.removeAllListeners(POS_EVENT_UPDATE);
|
||||
pointOfSaleEventEmitter.removeAllListeners(DID_OPEN_TABLES_EVENT_NAME);
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -31,11 +31,13 @@ import { JsonRpcProvider, Wallet } from 'ethers';
|
||||
import { getBoltzWsUrl } from '../app/functions/boltz/boltzEndpoitns';
|
||||
import { useSparkWallet } from './sparkContext';
|
||||
import { useWebView } from './webViewContext';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
export const RootstockSwapContext = createContext();
|
||||
|
||||
export const RootstockSwapProvider = ({ children }) => {
|
||||
const { sendWebViewRequest } = useWebView();
|
||||
const { authResetkey } = useAuthContext();
|
||||
const { sparkInformation } = useSparkWallet();
|
||||
const { accountMnemoinc } = useKeysContext();
|
||||
const { didGetToHomepage, minMaxLiquidSwapAmounts } = useAppStatus();
|
||||
@@ -44,6 +46,7 @@ export const RootstockSwapProvider = ({ children }) => {
|
||||
const [signer, setSigner] = useState(null);
|
||||
const [pendingNavigation, setPendingNavigation] = useState(null);
|
||||
|
||||
const isInitialRender = useRef(true);
|
||||
const wsRef = useRef(null);
|
||||
const intervalRef = useRef(null);
|
||||
const timeoutRef = useRef(null);
|
||||
@@ -372,6 +375,16 @@ export const RootstockSwapProvider = ({ children }) => {
|
||||
],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
cleanupRootstockListener();
|
||||
didRunSignerCreation.current = false;
|
||||
setSigner(null);
|
||||
}, [authResetkey]);
|
||||
|
||||
const contextValue = useMemo(() => {
|
||||
return {
|
||||
provider,
|
||||
|
||||
+118
-28
@@ -9,6 +9,7 @@ import {
|
||||
} from 'react';
|
||||
import {
|
||||
claimnSparkStaticDepositAddress,
|
||||
clearMnemonicCache,
|
||||
findTransactionTxFromTxHistory,
|
||||
getSparkBalance,
|
||||
getSparkStaticBitcoinL1AddressQuote,
|
||||
@@ -60,6 +61,7 @@ import {
|
||||
useWebView,
|
||||
} from './webViewContext';
|
||||
import { useGlobalContextProvider } from './context';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
export const isSendingPayingEventEmiiter = new EventEmitter();
|
||||
export const SENDING_PAYMENT_EVENT_NAME = 'SENDING_PAYMENT_EVENT';
|
||||
@@ -68,11 +70,12 @@ export const SENDING_PAYMENT_EVENT_NAME = 'SENDING_PAYMENT_EVENT';
|
||||
const SparkWalletManager = createContext(null);
|
||||
|
||||
const SparkWalletProvider = ({ children }) => {
|
||||
const { authResetkey } = useAuthContext();
|
||||
const { masterInfoObject } = useGlobalContextProvider();
|
||||
const { changeSparkConnectionState, sendWebViewRequest } = useWebView();
|
||||
const { accountMnemoinc, contactsPrivateKey, publicKey } = useKeysContext();
|
||||
const { currentWalletMnemoinc } = useActiveCustodyAccount();
|
||||
const { didGetToHomepage, appState } = useAppStatus();
|
||||
const { didGetToHomepage, appState, shouldResetStateRef } = useAppStatus();
|
||||
// const { liquidNodeInformation } = useNodeContext();
|
||||
const { toggleGlobalContactsInformation, globalContactsInformation } =
|
||||
useGlobalContacts();
|
||||
@@ -112,6 +115,8 @@ const SparkWalletProvider = ({ children }) => {
|
||||
const balancePollingTimeoutRef = useRef(null);
|
||||
const balancePollingAbortControllerRef = useRef(null);
|
||||
const currentPollingMnemonicRef = useRef(null);
|
||||
const isInitialRender = useRef(true);
|
||||
const authResetKeyRef = useRef(authResetkey);
|
||||
const showTokensInformation =
|
||||
masterInfoObject.enabledBTKNTokens === null
|
||||
? !!Object.keys(sparkInformation.tokens || {}).length
|
||||
@@ -123,6 +128,10 @@ const SparkWalletProvider = ({ children }) => {
|
||||
didRunNormalConnection || normalConnectionTimeout;
|
||||
const currentMnemonicRef = useRef(currentWalletMnemoinc);
|
||||
|
||||
useEffect(() => {
|
||||
authResetKeyRef.current = authResetkey;
|
||||
}, [authResetkey]);
|
||||
|
||||
useEffect(() => {
|
||||
sparkInfoRef.current = {
|
||||
balance: sparkInformation.balance,
|
||||
@@ -225,10 +234,14 @@ const SparkWalletProvider = ({ children }) => {
|
||||
if (didInitializeSendingPaymentEvent.current) return;
|
||||
didInitializeSendingPaymentEvent.current = true;
|
||||
|
||||
isSendingPayingEventEmiiter.addListener(
|
||||
SENDING_PAYMENT_EVENT_NAME,
|
||||
toggleIsSendingPayment,
|
||||
);
|
||||
if (
|
||||
!isSendingPayingEventEmiiter.listenerCount(SENDING_PAYMENT_EVENT_NAME)
|
||||
) {
|
||||
isSendingPayingEventEmiiter.addListener(
|
||||
SENDING_PAYMENT_EVENT_NAME,
|
||||
toggleIsSendingPayment,
|
||||
);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// This is a function that handles incoming transactions and formats it to required format
|
||||
@@ -683,14 +696,43 @@ const SparkWalletProvider = ({ children }) => {
|
||||
console.log('BLOCKING TRYING TO SET INTERVAL AGAIN');
|
||||
clearInterval(updatePendingPaymentsIntervalRef.current);
|
||||
}
|
||||
|
||||
const capturedAuthKey = authResetKeyRef.current;
|
||||
const capturedMnemonic = currentMnemonicRef.current;
|
||||
|
||||
updatePendingPaymentsIntervalRef.current = setInterval(async () => {
|
||||
try {
|
||||
if (AppState.currentState !== 'active') return;
|
||||
if (capturedAuthKey !== authResetKeyRef.current) {
|
||||
console.log('Auth key changed. Aborting interval.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (capturedMnemonic !== currentMnemonicRef.current) {
|
||||
console.log('Mnemonic changed. Aborting interval.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (AppState.currentState !== 'active') {
|
||||
console.log('App not active. Skipping interval.');
|
||||
return;
|
||||
}
|
||||
|
||||
await updateSparkTxStatus(
|
||||
currentMnemonicRef.current,
|
||||
sparkInfoRef.current.identityPubKey,
|
||||
sendWebViewRequest,
|
||||
);
|
||||
|
||||
if (
|
||||
capturedAuthKey !== authResetKeyRef.current ||
|
||||
capturedMnemonic !== currentMnemonicRef.current
|
||||
) {
|
||||
console.log(
|
||||
'Context changed during updateSparkTxStatus. Aborting getLRC20Transactions.',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await getLRC20Transactions({
|
||||
ownerPublicKeys: [sparkInfoRef.current.identityPubKey],
|
||||
sparkAddress: sparkInfoRef.current.sparkAddress,
|
||||
@@ -713,28 +755,30 @@ const SparkWalletProvider = ({ children }) => {
|
||||
isRunningAddListeners.current = false;
|
||||
};
|
||||
|
||||
const removeListeners = async () => {
|
||||
const removeListeners = async (onlyClearIntervals = false) => {
|
||||
console.log('Removing spark listeners');
|
||||
const runtime = await selectSparkRuntime(currentMnemonicRef.current);
|
||||
if (!prevAccountMnemoincRef.current) {
|
||||
prevAccountMnemoincRef.current = currentMnemonicRef.current;
|
||||
return;
|
||||
}
|
||||
const hashedMnemoinc = sha256Hash(prevAccountMnemoincRef.current);
|
||||
|
||||
if (runtime === 'native') {
|
||||
if (
|
||||
prevAccountMnemoincRef.current &&
|
||||
sparkWallet[hashedMnemoinc]?.listenerCount('transfer:claimed')
|
||||
) {
|
||||
sparkWallet[hashedMnemoinc]?.removeAllListeners('transfer:claimed');
|
||||
if (!onlyClearIntervals) {
|
||||
const runtime = await selectSparkRuntime(currentMnemonicRef.current);
|
||||
if (!prevAccountMnemoincRef.current) {
|
||||
prevAccountMnemoincRef.current = currentMnemonicRef.current;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
await sendWebViewRequestGlobal(OPERATION_TYPES.removeListeners, {
|
||||
mnemonic: prevAccountMnemoincRef.current,
|
||||
});
|
||||
const hashedMnemoinc = sha256Hash(prevAccountMnemoincRef.current);
|
||||
|
||||
if (runtime === 'native') {
|
||||
if (
|
||||
prevAccountMnemoincRef.current &&
|
||||
sparkWallet[hashedMnemoinc]?.listenerCount('transfer:claimed')
|
||||
) {
|
||||
sparkWallet[hashedMnemoinc]?.removeAllListeners('transfer:claimed');
|
||||
}
|
||||
} else {
|
||||
await sendWebViewRequestGlobal(OPERATION_TYPES.removeListeners, {
|
||||
mnemonic: prevAccountMnemoincRef.current,
|
||||
});
|
||||
}
|
||||
prevAccountMnemoincRef.current = currentMnemonicRef.current;
|
||||
}
|
||||
prevAccountMnemoincRef.current = currentMnemonicRef.current;
|
||||
|
||||
// Clear debounce timeout when removing listeners
|
||||
if (debounceTimeoutRef.current) {
|
||||
@@ -761,8 +805,54 @@ const SparkWalletProvider = ({ children }) => {
|
||||
currentPollingMnemonicRef.current = null;
|
||||
};
|
||||
|
||||
// Add event listeners to listen for bitcoin and lightning or spark transfers when receiving only when screen is active
|
||||
const resetSparkState = useCallback(async () => {
|
||||
// Reset refs to initial values
|
||||
await removeListeners(true);
|
||||
clearMnemonicCache();
|
||||
prevAccountMnemoincRef.current = null;
|
||||
isRunningAddListeners.current = false;
|
||||
depositAddressIntervalRef.current = null;
|
||||
updatePendingPaymentsIntervalRef.current = null;
|
||||
sparkInfoRef.current = {
|
||||
balance: 0,
|
||||
tokens: {},
|
||||
identityPubKey: '',
|
||||
sparkAddress: '',
|
||||
};
|
||||
handledTransfers.current = new Set();
|
||||
prevListenerType.current = null;
|
||||
prevAppState.current = 'active';
|
||||
prevAccountId.current = null;
|
||||
isSendingPaymentRef.current = false;
|
||||
balancePollingTimeoutRef.current = null;
|
||||
balancePollingAbortControllerRef.current = null;
|
||||
currentPollingMnemonicRef.current = null;
|
||||
|
||||
// Reset state variables
|
||||
setSparkConnectionError(null);
|
||||
setSparkInformation({
|
||||
balance: 0,
|
||||
tokens: {},
|
||||
transactions: [],
|
||||
identityPubKey: '',
|
||||
sparkAddress: '',
|
||||
didConnect: null,
|
||||
});
|
||||
setPendingNavigation(null);
|
||||
setDidRunNormalConnection(false);
|
||||
setNormalConnectionTimeout(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
|
||||
resetSparkState();
|
||||
}, [authResetkey]);
|
||||
|
||||
// Add event listeners to listen for bitcoin and lightning or spark transfers when receiving only when screen is active
|
||||
useEffect(() => {
|
||||
// Handle immediate background transitions synchronously(background events on android were not running)
|
||||
if (prevAppState.current !== appState && appState === 'background') {
|
||||
@@ -772,8 +862,7 @@ const SparkWalletProvider = ({ children }) => {
|
||||
|
||||
const timeoutId = setTimeout(async () => {
|
||||
if (!didGetToHomepage) return;
|
||||
if (!sparkInformation.didConnect) return;
|
||||
if (!sparkInformation.identityPubKey) return;
|
||||
if (!sparkInfoRef.current.identityPubKey) return;
|
||||
|
||||
const getListenerType = () => {
|
||||
if (appState === 'active') return 'full';
|
||||
@@ -820,6 +909,7 @@ const SparkWalletProvider = ({ children }) => {
|
||||
console.log('l1Deposit check running....');
|
||||
if (AppState.currentState !== 'active') return;
|
||||
if (isSendingPaymentRef.current) return;
|
||||
if (!currentMnemonicRef.current) return;
|
||||
const allTxs = await getAllSparkTransactions({
|
||||
accountId: sparkInfoRef.current.identityPubKey,
|
||||
});
|
||||
|
||||
@@ -26,6 +26,7 @@ import DeviceInfo, {
|
||||
import { getLocalStorageItem, setLocalStorageItem } from '../app/functions';
|
||||
import { useAppStatus } from './appStatus';
|
||||
import { useActiveCustodyAccount } from './activeAccount';
|
||||
import { useAuthContext } from './authContext';
|
||||
|
||||
export const OPERATION_TYPES = {
|
||||
initWallet: 'initializeSparkWallet',
|
||||
@@ -101,7 +102,6 @@ const WASM_ERRORS = [
|
||||
let handshakeComplete = false;
|
||||
let forceReactNativeUse = null;
|
||||
let globalSendWebViewRequest = null;
|
||||
const BACKGROUND_THRESHOLD_MS = 3 * 60 * 1000;
|
||||
|
||||
const WebViewContext = createContext(null);
|
||||
|
||||
@@ -150,6 +150,7 @@ export const getHandshakeComplete = () => {
|
||||
};
|
||||
|
||||
export const WebViewProvider = ({ children }) => {
|
||||
const { authResetkey } = useAuthContext();
|
||||
const { currentWalletMnemoinc } = useActiveCustodyAccount();
|
||||
const { appState, isConnectedToTheInternet, didGetToHomepage } =
|
||||
useAppStatus();
|
||||
@@ -171,7 +172,8 @@ export const WebViewProvider = ({ children }) => {
|
||||
const prevConnectionStatus = useRef(isConnectedToTheInternet);
|
||||
const internetConnectionRef = useRef(isConnectedToTheInternet);
|
||||
const walletInitialized = useRef(false);
|
||||
const backgroundTimeRef = useRef(null);
|
||||
const isInitialRender = useRef(true);
|
||||
const currentWalletMnemoincRef = useRef(currentWalletMnemoinc);
|
||||
const didRunInit = useRef(null);
|
||||
const didGetToHomepageRef = useRef(didGetToHomepage);
|
||||
const [changeSparkConnectionState, setChangeSparkConnectionState] = useState({
|
||||
@@ -179,6 +181,19 @@ export const WebViewProvider = ({ children }) => {
|
||||
count: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
currentWalletMnemoincRef.current = currentWalletMnemoinc;
|
||||
}, [currentWalletMnemoinc]);
|
||||
|
||||
// reset webview when app is stale in background
|
||||
useEffect(() => {
|
||||
if (isInitialRender.current) {
|
||||
isInitialRender.current = false;
|
||||
return;
|
||||
}
|
||||
blockAndResetWebview();
|
||||
}, [authResetkey]);
|
||||
|
||||
useEffect(() => {
|
||||
didGetToHomepageRef.current = didGetToHomepage;
|
||||
}, [didGetToHomepage]);
|
||||
@@ -321,7 +336,6 @@ export const WebViewProvider = ({ children }) => {
|
||||
|
||||
if (appState === 'background') {
|
||||
console.log('App going to background - clearing all timeouts');
|
||||
backgroundTimeRef.current = Date.now();
|
||||
// Clear everything to prevent timeout issues on background
|
||||
Object.values(activeTimeoutsRef.current).forEach(t =>
|
||||
clearTimeout(t.timeoutId),
|
||||
@@ -333,10 +347,6 @@ export const WebViewProvider = ({ children }) => {
|
||||
} else if (appState === 'active') {
|
||||
console.log('App returned to foreground');
|
||||
|
||||
const timeInBackground = backgroundTimeRef.current
|
||||
? Date.now() - backgroundTimeRef.current
|
||||
: 0;
|
||||
|
||||
// Wait for internet connection before proceeding
|
||||
if (!isConnectedToTheInternet) {
|
||||
console.log('Waiting for internet connection before processing...');
|
||||
@@ -360,10 +370,7 @@ export const WebViewProvider = ({ children }) => {
|
||||
connectionChanged && isConnectedToTheInternet;
|
||||
|
||||
if (justBecameActive || connectionJustRestored) {
|
||||
if (
|
||||
timeInBackground > BACKGROUND_THRESHOLD_MS ||
|
||||
(!nonceVerified.current && !isResetting.current)
|
||||
) {
|
||||
if (!nonceVerified.current && !isResetting.current) {
|
||||
console.log('Background time exceeded threshold - reloading WebView');
|
||||
blockAndResetWebview();
|
||||
} else {
|
||||
@@ -384,8 +391,6 @@ export const WebViewProvider = ({ children }) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backgroundTimeRef.current = null;
|
||||
}
|
||||
|
||||
previousAppState.current = appState;
|
||||
@@ -577,12 +582,7 @@ export const WebViewProvider = ({ children }) => {
|
||||
forceReactNativeUse = true;
|
||||
}
|
||||
},
|
||||
[
|
||||
decryptMessage,
|
||||
resetWebViewState,
|
||||
currentWalletMnemoinc,
|
||||
processQueuedRequests,
|
||||
],
|
||||
[decryptMessage, resetWebViewState, processQueuedRequests],
|
||||
);
|
||||
|
||||
const sendWebViewRequestInternal = useCallback(
|
||||
@@ -903,12 +903,12 @@ export const WebViewProvider = ({ children }) => {
|
||||
if (didRunInit.current) return;
|
||||
didRunInit.current = true;
|
||||
|
||||
const androidAPI = DeviceInfo.getApiLevelSync();
|
||||
if (androidAPI == 33 || androidAPI == 34) {
|
||||
console.warn(`Skipping handshake on Android API ${androidAPI}`);
|
||||
forceReactNativeUse = true;
|
||||
return;
|
||||
}
|
||||
// const androidAPI = DeviceInfo.getApiLevelSync();
|
||||
// if (androidAPI == 33 || androidAPI == 34) {
|
||||
// console.warn(`Skipping handshake on Android API ${androidAPI}`);
|
||||
// forceReactNativeUse = true;
|
||||
// return;
|
||||
// }
|
||||
|
||||
const savedVariable = await getLocalStorageItem('FORCE_REACT_NATIVE');
|
||||
|
||||
@@ -955,15 +955,15 @@ export const WebViewProvider = ({ children }) => {
|
||||
if (
|
||||
(handshakeComplete &&
|
||||
!walletInitialized.current &&
|
||||
currentWalletMnemoinc) ||
|
||||
(currentWalletMnemoinc && connectionJustRestored)
|
||||
currentWalletMnemoincRef.current) ||
|
||||
(currentWalletMnemoincRef.current && connectionJustRestored)
|
||||
) {
|
||||
console.log('Re-initializing wallet before processing queue');
|
||||
try {
|
||||
// No need to handle any state changes here, handled inside of the promise. But this might be where the stale connection state comes from. if a request is sent to the webview but not responded to the change to react-native woudnt have happpened before leaving everything in "not connected to spark".
|
||||
const response = await sendWebViewRequestInternal(
|
||||
OPERATION_TYPES.initWallet,
|
||||
{ mnemonic: currentWalletMnemoinc },
|
||||
{ mnemonic: currentWalletMnemoincRef.current },
|
||||
true,
|
||||
);
|
||||
if (!response?.isConnected) throw new Error('Wallet init failed');
|
||||
@@ -986,7 +986,10 @@ export const WebViewProvider = ({ children }) => {
|
||||
`Processing ${queuedRequests.current.length} queued requests`,
|
||||
);
|
||||
|
||||
if (queuedRequests.current.length === 0) {
|
||||
if (
|
||||
queuedRequests.current.length === 0 ||
|
||||
!currentWalletMnemoincRef.current
|
||||
) {
|
||||
isResetting.current = false;
|
||||
return;
|
||||
}
|
||||
@@ -1007,7 +1010,7 @@ export const WebViewProvider = ({ children }) => {
|
||||
|
||||
isResetting.current = false;
|
||||
},
|
||||
[currentWalletMnemoinc, sendWebViewRequestInternal],
|
||||
[sendWebViewRequestInternal],
|
||||
);
|
||||
|
||||
const getCustomUserAgent = useCallback(() => {
|
||||
|
||||
Reference in New Issue
Block a user