@oxyhq/services 5.16.37 → 5.16.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/ui/context/OxyContext.js +84 -14
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +42 -4
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/stores/transferStore.js +4 -0
- package/lib/commonjs/ui/stores/transferStore.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +85 -15
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +42 -4
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/stores/transferStore.js +4 -0
- package/lib/module/ui/stores/transferStore.js.map +1 -1
- package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/ui/stores/transferStore.d.ts +1 -0
- package/lib/typescript/ui/stores/transferStore.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/ui/context/OxyContext.tsx +81 -14
- package/src/ui/context/hooks/useAuthOperations.ts +42 -4
- package/src/ui/stores/transferStore.ts +6 -0
|
@@ -23,6 +23,7 @@ export interface TransferState {
|
|
|
23
23
|
markRestored: () => void;
|
|
24
24
|
cleanupExpired: () => void;
|
|
25
25
|
reset: () => void;
|
|
26
|
+
clearAll: () => void;
|
|
26
27
|
}
|
|
27
28
|
export declare const useTransferStore: import("zustand").UseBoundStore<import("zustand").StoreApi<TransferState>>;
|
|
28
29
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transferStore.d.ts","sourceRoot":"","sources":["../../../../src/ui/stores/transferStore.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAE5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAGhD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,OAAO,CAAC;IAGpB,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChH,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACjE,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC;IAC7F,sBAAsB,EAAE,MAAM,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IACpF,mBAAmB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACzC,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACvG,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"transferStore.d.ts","sourceRoot":"","sources":["../../../../src/ui/stores/transferStore.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;CAC3C;AAED,MAAM,WAAW,aAAa;IAE5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAGhD,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,OAAO,CAAC;IAGpB,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAChH,eAAe,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACjE,iBAAiB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC;IAC7F,sBAAsB,EAAE,MAAM,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IACpF,mBAAmB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IACzC,mBAAmB,EAAE,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzD,kBAAkB,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACvG,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;CACtB;AAUD,eAAO,MAAM,gBAAgB,4EA8I1B,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,8BAA8B;;;CAO1C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oxyhq/services",
|
|
3
|
-
"version": "5.16.
|
|
3
|
+
"version": "5.16.38",
|
|
4
4
|
"description": "Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
useCallback,
|
|
5
5
|
useContext,
|
|
6
6
|
useEffect,
|
|
7
|
+
useLayoutEffect,
|
|
7
8
|
useMemo,
|
|
8
9
|
useRef,
|
|
9
10
|
useState,
|
|
@@ -211,6 +212,15 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
211
212
|
|
|
212
213
|
const { storage, isReady: isStorageReady } = useStorage({ onError, logger });
|
|
213
214
|
|
|
215
|
+
// Invalidate KeyManager cache on mount to prevent stale cache issues
|
|
216
|
+
// useLayoutEffect runs synchronously after render but before paint, ensuring cache
|
|
217
|
+
// invalidation happens before any async operations start
|
|
218
|
+
useLayoutEffect(() => {
|
|
219
|
+
if (Platform.OS !== 'web') {
|
|
220
|
+
KeyManager.invalidateCache();
|
|
221
|
+
}
|
|
222
|
+
}, []);
|
|
223
|
+
|
|
214
224
|
// Identity integrity check and auto-restore on startup
|
|
215
225
|
// Skip on web platform - identity storage is only available on native platforms
|
|
216
226
|
useEffect(() => {
|
|
@@ -219,9 +229,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
219
229
|
|
|
220
230
|
const checkAndRestoreIdentity = async () => {
|
|
221
231
|
try {
|
|
222
|
-
//
|
|
223
|
-
// This prevents stale cache from previous session from showing incorrect state
|
|
224
|
-
KeyManager.invalidateCache();
|
|
232
|
+
// Cache was already invalidated synchronously above
|
|
225
233
|
|
|
226
234
|
// Check if identity exists and verify integrity
|
|
227
235
|
const hasIdentity = await KeyManager.hasIdentity();
|
|
@@ -352,9 +360,17 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
352
360
|
[importIdentityBase]
|
|
353
361
|
);
|
|
354
362
|
|
|
363
|
+
// Storage keys for transfer codes
|
|
364
|
+
const TRANSFER_CODES_STORAGE_KEY = `${storageKeyPrefix}_transfer_codes`;
|
|
365
|
+
const ACTIVE_TRANSFER_STORAGE_KEY = `${storageKeyPrefix}_active_transfer_id`;
|
|
366
|
+
|
|
355
367
|
// Clear all account data when identity is lost (for accounts app)
|
|
356
368
|
// In accounts app, identity = account, so losing identity means losing everything
|
|
357
369
|
const clearAllAccountData = useCallback(async (): Promise<void> => {
|
|
370
|
+
if (__DEV__) {
|
|
371
|
+
logger('Clearing all account data - identity changed or lost');
|
|
372
|
+
}
|
|
373
|
+
|
|
358
374
|
// Clear TanStack Query cache (in-memory)
|
|
359
375
|
queryClient.clear();
|
|
360
376
|
|
|
@@ -386,9 +402,30 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
386
402
|
// Reset account store
|
|
387
403
|
useAccountStore.getState().reset();
|
|
388
404
|
|
|
405
|
+
// CRITICAL: Clear ALL transfer codes and active transfer state
|
|
406
|
+
// This prevents transfer state from previous identity from lingering
|
|
407
|
+
if (storage) {
|
|
408
|
+
try {
|
|
409
|
+
await storage.removeItem(TRANSFER_CODES_STORAGE_KEY);
|
|
410
|
+
await storage.removeItem(ACTIVE_TRANSFER_STORAGE_KEY);
|
|
411
|
+
|
|
412
|
+
// Also clear Zustand transfer store
|
|
413
|
+
useTransferStore.getState().clearAll();
|
|
414
|
+
|
|
415
|
+
if (__DEV__) {
|
|
416
|
+
logger('Cleared all transfer state');
|
|
417
|
+
}
|
|
418
|
+
} catch (error) {
|
|
419
|
+
logger('Failed to clear transfer state', error);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
389
423
|
// Clear HTTP service cache
|
|
390
424
|
oxyServices.clearCache();
|
|
391
|
-
|
|
425
|
+
|
|
426
|
+
// Force KeyManager cache invalidation
|
|
427
|
+
KeyManager.invalidateCache();
|
|
428
|
+
}, [queryClient, storage, clearSessionState, logger, oxyServices, TRANSFER_CODES_STORAGE_KEY, ACTIVE_TRANSFER_STORAGE_KEY]);
|
|
392
429
|
|
|
393
430
|
// Extract Zustand store functions early (before they're used in callbacks)
|
|
394
431
|
const getAllPendingTransfersStore = useTransferStore((state) => state.getAllPendingTransfers);
|
|
@@ -582,6 +619,8 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
582
619
|
try {
|
|
583
620
|
// CRITICAL: Get current identity's public key first
|
|
584
621
|
// Only restore sessions that belong to this identity
|
|
622
|
+
// Force cache invalidation to ensure we get the actual current identity
|
|
623
|
+
KeyManager.invalidateCache();
|
|
585
624
|
const currentPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
586
625
|
|
|
587
626
|
const storedSessionIdsJson = await storage.getItem(storageKeys.sessionIds);
|
|
@@ -591,13 +630,21 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
591
630
|
// If no identity exists, clear all sessions and return
|
|
592
631
|
if (!currentPublicKey) {
|
|
593
632
|
if (storedSessionIds.length > 0 || storedActiveSessionId) {
|
|
633
|
+
if (__DEV__) {
|
|
634
|
+
logger('No identity found - clearing all stored sessions to prevent cross-identity data leak');
|
|
635
|
+
}
|
|
594
636
|
await clearSessionState();
|
|
595
637
|
}
|
|
596
638
|
setTokenReady(true);
|
|
597
639
|
return;
|
|
598
640
|
}
|
|
599
641
|
|
|
642
|
+
if (__DEV__) {
|
|
643
|
+
logger('Restoring sessions for identity', { publicKey: currentPublicKey.substring(0, 16) + '...', sessionCount: storedSessionIds.length });
|
|
644
|
+
}
|
|
645
|
+
|
|
600
646
|
const validSessions: ClientSession[] = [];
|
|
647
|
+
const invalidSessionIds: string[] = []; // Track invalid sessions for batch removal
|
|
601
648
|
|
|
602
649
|
if (storedSessionIds.length > 0) {
|
|
603
650
|
for (const sessionId of storedSessionIds) {
|
|
@@ -605,14 +652,18 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
605
652
|
const validation = await oxyServices.validateSession(sessionId, { useHeaderValidation: true });
|
|
606
653
|
if (validation?.valid && validation.user) {
|
|
607
654
|
// CRITICAL: Verify session belongs to current identity
|
|
608
|
-
//
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
if (validation.user.id !== currentPublicKey) {
|
|
612
|
-
// Session belongs to different identity - skip it
|
|
655
|
+
// Compare session's publicKey to current identity's publicKey
|
|
656
|
+
if (validation.user.publicKey !== currentPublicKey) {
|
|
657
|
+
// Session belongs to different identity - skip it and log warning
|
|
613
658
|
if (__DEV__) {
|
|
614
|
-
logger('Skipping session from different identity during restoration'
|
|
659
|
+
logger('CRITICAL: Skipping session from different identity during restoration', {
|
|
660
|
+
sessionPublicKey: validation.user.publicKey?.substring(0, 16) + '...',
|
|
661
|
+
currentPublicKey: currentPublicKey.substring(0, 16) + '...',
|
|
662
|
+
sessionId: sessionId.substring(0, 16) + '...',
|
|
663
|
+
});
|
|
615
664
|
}
|
|
665
|
+
// Mark for batch removal
|
|
666
|
+
invalidSessionIds.push(sessionId);
|
|
616
667
|
continue;
|
|
617
668
|
}
|
|
618
669
|
|
|
@@ -638,6 +689,24 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
638
689
|
}
|
|
639
690
|
}
|
|
640
691
|
|
|
692
|
+
// Batch remove invalid sessions from storage (performance optimization)
|
|
693
|
+
if (invalidSessionIds.length > 0) {
|
|
694
|
+
try {
|
|
695
|
+
// Use Set for O(n) lookup instead of O(n²) with includes()
|
|
696
|
+
const invalidSessionSet = new Set(invalidSessionIds);
|
|
697
|
+
const updatedIds = storedSessionIds.filter(id => !invalidSessionSet.has(id));
|
|
698
|
+
await storage.setItem(storageKeys.sessionIds, JSON.stringify(updatedIds));
|
|
699
|
+
if (__DEV__) {
|
|
700
|
+
logger('Removed invalid sessions from storage', { count: invalidSessionIds.length });
|
|
701
|
+
}
|
|
702
|
+
} catch (cleanupError) {
|
|
703
|
+
// Ignore cleanup errors - will be cleaned on next restart
|
|
704
|
+
if (__DEV__) {
|
|
705
|
+
logger('Failed to remove invalid sessions from storage', cleanupError);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
641
710
|
if (validSessions.length > 0) {
|
|
642
711
|
updateSessions(validSessions, { merge: false });
|
|
643
712
|
}
|
|
@@ -752,13 +821,11 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
|
|
|
752
821
|
}, [isAuthenticatedFromStore, isAuthenticatedFromSessions]);
|
|
753
822
|
|
|
754
823
|
// Get userId from JWT token (MongoDB ObjectId) for socket room matching
|
|
755
|
-
// user.id
|
|
756
|
-
// The JWT token's userId field contains the MongoDB ObjectId
|
|
824
|
+
// user.id contains the MongoDB ObjectId, user.publicKey contains the cryptographic public key
|
|
757
825
|
const userId = oxyServices.getCurrentUserId() || user?.id;
|
|
758
826
|
|
|
759
827
|
// Use Zustand store for transfer state management
|
|
760
|
-
|
|
761
|
-
const ACTIVE_TRANSFER_STORAGE_KEY = `${storageKeyPrefix}_active_transfer_id`;
|
|
828
|
+
// Storage keys are defined above (TRANSFER_CODES_STORAGE_KEY, ACTIVE_TRANSFER_STORAGE_KEY)
|
|
762
829
|
const isRestored = useTransferStore((state) => state.isRestored);
|
|
763
830
|
const restoreFromStorage = useTransferStore((state) => state.restoreFromStorage);
|
|
764
831
|
const markRestored = useTransferStore((state) => state.markRestored);
|
|
@@ -91,13 +91,28 @@ export const useAuthOperations = ({
|
|
|
91
91
|
const clearSessionsIfIdentityChanged = useCallback(
|
|
92
92
|
async (oldPublicKey: string | null, newPublicKey: string): Promise<void> => {
|
|
93
93
|
if (oldPublicKey && oldPublicKey !== newPublicKey) {
|
|
94
|
+
if (__DEV__ && logger) {
|
|
95
|
+
logger('CRITICAL: Identity changed - clearing all session data', {
|
|
96
|
+
oldPublicKey: oldPublicKey.substring(0, 16) + '...',
|
|
97
|
+
newPublicKey: newPublicKey.substring(0, 16) + '...',
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
// Clear all session state to prevent old identity's data from showing up
|
|
95
102
|
await clearSessionState();
|
|
96
|
-
|
|
103
|
+
|
|
104
|
+
// Logout from auth store (clears user, isAuthenticated, etc.)
|
|
97
105
|
logoutStore();
|
|
106
|
+
|
|
107
|
+
// Force KeyManager cache invalidation
|
|
108
|
+
KeyManager.invalidateCache();
|
|
109
|
+
|
|
110
|
+
if (__DEV__ && logger) {
|
|
111
|
+
logger('Session state cleared for new identity');
|
|
112
|
+
}
|
|
98
113
|
}
|
|
99
114
|
},
|
|
100
|
-
[clearSessionState, logoutStore]
|
|
115
|
+
[clearSessionState, logoutStore, logger]
|
|
101
116
|
);
|
|
102
117
|
|
|
103
118
|
/**
|
|
@@ -311,10 +326,18 @@ export const useAuthOperations = ({
|
|
|
311
326
|
// CRITICAL: Get old public key before creating new identity
|
|
312
327
|
// If identity changes, we must clear all session data to prevent data leakage
|
|
313
328
|
const oldPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
329
|
+
|
|
330
|
+
if (__DEV__ && logger) {
|
|
331
|
+
logger('Creating new identity', { hadPreviousIdentity: !!oldPublicKey });
|
|
332
|
+
}
|
|
314
333
|
|
|
315
334
|
// Generate new key pair directly (works offline)
|
|
316
335
|
const { publicKey, privateKey } = await KeyManager.generateKeyPair();
|
|
317
336
|
await KeyManager.importKeyPair(privateKey);
|
|
337
|
+
|
|
338
|
+
if (__DEV__ && logger) {
|
|
339
|
+
logger('Identity keys generated', { publicKey: publicKey.substring(0, 16) + '...' });
|
|
340
|
+
}
|
|
318
341
|
|
|
319
342
|
// Clear sessions if identity changed (prevents data leakage)
|
|
320
343
|
await clearSessionsIfIdentityChanged(oldPublicKey, publicKey);
|
|
@@ -331,14 +354,18 @@ export const useAuthOperations = ({
|
|
|
331
354
|
// Mark as synced (Zustand store + storage)
|
|
332
355
|
await storage.setItem('oxy_identity_synced', 'true');
|
|
333
356
|
setIdentitySynced(true);
|
|
357
|
+
|
|
358
|
+
if (__DEV__ && logger) {
|
|
359
|
+
logger('Identity synced with server successfully');
|
|
360
|
+
}
|
|
334
361
|
|
|
335
362
|
return {
|
|
336
363
|
synced: true,
|
|
337
364
|
};
|
|
338
365
|
} catch (syncError) {
|
|
339
366
|
// Offline or server error - identity is created locally but not synced
|
|
340
|
-
if (__DEV__) {
|
|
341
|
-
|
|
367
|
+
if (__DEV__ && logger) {
|
|
368
|
+
logger('Identity created locally (offline), will sync when online', syncError);
|
|
342
369
|
}
|
|
343
370
|
|
|
344
371
|
return {
|
|
@@ -489,6 +516,13 @@ export const useAuthOperations = ({
|
|
|
489
516
|
// CRITICAL: Get old public key before importing new identity
|
|
490
517
|
// If identity changes, we must clear all session data to prevent data leakage
|
|
491
518
|
const oldPublicKey = await KeyManager.getPublicKey().catch(() => null);
|
|
519
|
+
|
|
520
|
+
if (__DEV__ && logger) {
|
|
521
|
+
logger('Importing identity from backup', {
|
|
522
|
+
hadPreviousIdentity: !!oldPublicKey,
|
|
523
|
+
backupPublicKey: backupData.publicKey.substring(0, 16) + '...'
|
|
524
|
+
});
|
|
525
|
+
}
|
|
492
526
|
|
|
493
527
|
// Decrypt private key from backup data
|
|
494
528
|
const Crypto = await import('expo-crypto');
|
|
@@ -525,6 +559,10 @@ export const useAuthOperations = ({
|
|
|
525
559
|
|
|
526
560
|
// Import the key pair
|
|
527
561
|
const publicKey = await KeyManager.importKeyPair(privateKey);
|
|
562
|
+
|
|
563
|
+
if (__DEV__ && logger) {
|
|
564
|
+
logger('Identity keys imported', { publicKey: publicKey.substring(0, 16) + '...' });
|
|
565
|
+
}
|
|
528
566
|
|
|
529
567
|
// Verify public key matches
|
|
530
568
|
if (publicKey !== backupData.publicKey) {
|
|
@@ -31,6 +31,7 @@ export interface TransferState {
|
|
|
31
31
|
markRestored: () => void;
|
|
32
32
|
cleanupExpired: () => void;
|
|
33
33
|
reset: () => void;
|
|
34
|
+
clearAll: () => void; // Alias for reset - use when clearing on identity change for semantic clarity
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
const FIFTEEN_MINUTES = 15 * 60 * 1000;
|
|
@@ -178,6 +179,11 @@ export const useTransferStore = create<TransferState>((set, get) => ({
|
|
|
178
179
|
reset: () => {
|
|
179
180
|
set(initialState);
|
|
180
181
|
},
|
|
182
|
+
|
|
183
|
+
clearAll: () => {
|
|
184
|
+
// Delegate to reset to maintain single source of truth
|
|
185
|
+
get().reset();
|
|
186
|
+
},
|
|
181
187
|
}));
|
|
182
188
|
|
|
183
189
|
/**
|