@oxyhq/services 5.16.28 → 5.16.29

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.
Files changed (28) hide show
  1. package/lib/commonjs/crypto/keyManager.js +3 -0
  2. package/lib/commonjs/crypto/keyManager.js.map +1 -1
  3. package/lib/commonjs/ui/context/OxyContext.js +70 -17
  4. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  5. package/lib/commonjs/ui/hooks/useTransferQueries.js +1 -64
  6. package/lib/commonjs/ui/hooks/useTransferQueries.js.map +1 -1
  7. package/lib/commonjs/ui/stores/transferStore.js +1 -9
  8. package/lib/commonjs/ui/stores/transferStore.js.map +1 -1
  9. package/lib/module/crypto/keyManager.js +3 -0
  10. package/lib/module/crypto/keyManager.js.map +1 -1
  11. package/lib/module/ui/context/OxyContext.js +70 -17
  12. package/lib/module/ui/context/OxyContext.js.map +1 -1
  13. package/lib/module/ui/hooks/useTransferQueries.js +0 -61
  14. package/lib/module/ui/hooks/useTransferQueries.js.map +1 -1
  15. package/lib/module/ui/stores/transferStore.js +0 -7
  16. package/lib/module/ui/stores/transferStore.js.map +1 -1
  17. package/lib/typescript/crypto/keyManager.d.ts +2 -1
  18. package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
  19. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  20. package/lib/typescript/ui/hooks/useTransferQueries.d.ts +0 -28
  21. package/lib/typescript/ui/hooks/useTransferQueries.d.ts.map +1 -1
  22. package/lib/typescript/ui/stores/transferStore.d.ts +0 -4
  23. package/lib/typescript/ui/stores/transferStore.d.ts.map +1 -1
  24. package/package.json +1 -1
  25. package/src/crypto/keyManager.ts +5 -1
  26. package/src/ui/context/OxyContext.tsx +67 -13
  27. package/src/ui/hooks/useTransferQueries.ts +1 -67
  28. package/src/ui/stores/transferStore.ts +0 -6
@@ -3,22 +3,8 @@ import type { OxyServices } from '../../core';
3
3
  * Query keys for transfer-related queries
4
4
  */
5
5
  export declare const transferQueryKeys: {
6
- all: readonly ["transfers"];
7
- completion: (transferId: string) => readonly ["transfers", "completion", string];
8
6
  pending: () => readonly ["transfers", "pending"];
9
7
  };
10
- /**
11
- * Hook to check if a transfer was completed
12
- * Only runs when authenticated and transferId is provided
13
- */
14
- export declare const useCheckTransferCompletion: (transferId: string | null, enabled?: boolean) => import("@tanstack/react-query").UseQueryResult<{
15
- completed: boolean;
16
- transferId?: string;
17
- sourceDeviceId?: string;
18
- publicKey?: string;
19
- transferCode?: string;
20
- completedAt?: string;
21
- } | null, any>;
22
8
  /**
23
9
  * Hook to check all pending transfers for completion
24
10
  * Used when app comes back online
@@ -37,18 +23,4 @@ export declare const useCheckPendingTransfers: (oxyServices?: OxyServices | null
37
23
  completedAt?: string;
38
24
  };
39
25
  }[], Error>;
40
- /**
41
- * Hook version that uses useOxy() - for use outside OxyContext
42
- */
43
- export declare const useCheckPendingTransfersWithContext: () => import("@tanstack/react-query").UseQueryResult<{
44
- transferId: string;
45
- completed: boolean;
46
- data?: {
47
- transferId?: string;
48
- sourceDeviceId?: string;
49
- publicKey?: string;
50
- transferCode?: string;
51
- completedAt?: string;
52
- };
53
- }[], Error>;
54
26
  //# sourceMappingURL=useTransferQueries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useTransferQueries.d.ts","sourceRoot":"","sources":["../../../../src/ui/hooks/useTransferQueries.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,iBAAiB;;6BAEH,MAAM;;CAEhC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GAAI,YAAY,MAAM,GAAG,IAAI,EAAE,UAAS,OAAc;eAYxE,OAAO;iBACL,MAAM;qBACF,MAAM;gBACX,MAAM;mBACH,MAAM;kBACP,MAAM;cAgC7B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,cAAc,WAAW,GAAG,IAAI,EAChC,kBAAkB,OAAO;gBAaP,MAAM;eACP,OAAO;WACX;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;WA2DR,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mCAAmC;gBAxE5B,MAAM;eACP,OAAO;WACX;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;WAmER,CAAC"}
1
+ {"version":3,"file":"useTransferQueries.d.ts","sourceRoot":"","sources":["../../../../src/ui/hooks/useTransferQueries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,iBAAiB;;CAE7B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,GACnC,cAAc,WAAW,GAAG,IAAI,EAChC,kBAAkB,OAAO;gBAaP,MAAM;eACP,OAAO;WACX;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;WA2DR,CAAC"}
@@ -32,8 +32,4 @@ export declare const useTransferCodesForPersistence: () => {
32
32
  transferCodes: Record<string, TransferCodeData>;
33
33
  activeTransferId: string | null;
34
34
  };
35
- /**
36
- * Hook to check if store has been restored
37
- */
38
- export declare const useTransferStoreRestored: () => boolean;
39
35
  //# sourceMappingURL=transferStore.d.ts.map
@@ -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;CACnB;AAUD,eAAO,MAAM,gBAAgB,4EAyI1B,CAAC;AAEJ;;GAEG;AACH,eAAO,MAAM,8BAA8B;;;CAO1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,eAEpC,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;CACnB;AAUD,eAAO,MAAM,gBAAgB,4EAyI1B,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.28",
3
+ "version": "5.16.29",
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",
@@ -124,8 +124,9 @@ export class KeyManager {
124
124
  /**
125
125
  * Invalidate cached identity state
126
126
  * Called internally when identity is created/deleted/imported
127
+ * Can also be called externally to force a fresh state check (e.g., on app startup)
127
128
  */
128
- private static invalidateCache(): void {
129
+ static invalidateCache(): void {
129
130
  KeyManager.cachedPublicKey = null;
130
131
  KeyManager.cachedHasIdentity = null;
131
132
  }
@@ -434,6 +435,9 @@ export class KeyManager {
434
435
  return false; // Identity storage is only available on native platforms
435
436
  }
436
437
  try {
438
+ // Invalidate cache before restoring to ensure fresh state
439
+ KeyManager.invalidateCache();
440
+
437
441
  const store = await initSecureStore();
438
442
 
439
443
  // Check if backup exists
@@ -165,7 +165,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
165
165
 
166
166
  const {
167
167
  user,
168
- isAuthenticated,
168
+ isAuthenticated: isAuthenticatedFromStore,
169
169
  isLoading,
170
170
  error,
171
171
  loginSuccess,
@@ -219,12 +219,16 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
219
219
 
220
220
  const checkAndRestoreIdentity = async () => {
221
221
  try {
222
+ // CRITICAL: Invalidate cache on app startup to ensure fresh state check
223
+ // This prevents stale cache from previous session from showing incorrect state
224
+ KeyManager.invalidateCache();
225
+
222
226
  // Check if identity exists and verify integrity
223
227
  const hasIdentity = await KeyManager.hasIdentity();
224
228
  if (hasIdentity) {
225
229
  const isValid = await KeyManager.verifyIdentityIntegrity();
226
230
  if (!isValid) {
227
- // Try to restore from backup
231
+ // Try to restore from backup (cache will be invalidated inside restoreIdentityFromBackup)
228
232
  const restored = await KeyManager.restoreIdentityFromBackup();
229
233
  if (__DEV__) {
230
234
  logger(restored
@@ -237,7 +241,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
237
241
  await KeyManager.backupIdentity();
238
242
  }
239
243
  } else {
240
- // No identity - try to restore from backup
244
+ // No identity - try to restore from backup (cache will be invalidated inside restoreIdentityFromBackup)
241
245
  const restored = await KeyManager.restoreIdentityFromBackup();
242
246
  if (restored && __DEV__) {
243
247
  logger('Identity restored from backup on startup');
@@ -254,9 +258,6 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
254
258
  checkAndRestoreIdentity();
255
259
  }, [storage, isStorageReady, logger]);
256
260
 
257
- // Offline queuing is now handled by TanStack Query mutations
258
- // No need for custom offline queue
259
-
260
261
  const {
261
262
  currentLanguage,
262
263
  metadata: currentLanguageMetadata,
@@ -276,7 +277,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
276
277
  const {
277
278
  sessions,
278
279
  activeSessionId,
279
- setActiveSessionId,
280
+ setActiveSessionId: setActiveSessionIdFromHook,
280
281
  updateSessions,
281
282
  switchSession,
282
283
  refreshSessions,
@@ -313,7 +314,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
313
314
  storage,
314
315
  sessions,
315
316
  activeSessionId,
316
- setActiveSessionId,
317
+ setActiveSessionId: setActiveSessionIdFromHook,
317
318
  updateSessions,
318
319
  saveActiveSessionId,
319
320
  clearSessionState,
@@ -559,7 +560,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
559
560
  clearTimeout(checkTimeout);
560
561
  }
561
562
  };
562
- }, [oxyServices, storage, syncIdentity, logger, hasIdentity, isAuthenticated]);
563
+ }, [oxyServices, storage, syncIdentity, logger, hasIdentity]);
563
564
 
564
565
  const { getDeviceSessions, logoutAllDeviceSessions, updateDeviceName } = useDeviceManagement({
565
566
  oxyServices,
@@ -631,6 +632,24 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
631
632
  // Don't log expected session errors during restoration
632
633
  } else if (isTimeoutOrNetworkError(switchError)) {
633
634
  // Timeout/network error - non-critical, don't block
635
+ // However, if we have valid sessions, we should still set activeSessionId
636
+ // so that isAuthenticated can be computed correctly
637
+ if (validSessions.length > 0) {
638
+ const matchingSession = validSessions.find(s => s.sessionId === storedActiveSessionId);
639
+ if (matchingSession) {
640
+ // Set active session even if validation timed out (offline scenario)
641
+ setActiveSessionIdFromHook(storedActiveSessionId);
642
+ // Try to get user from session if possible (might fail offline, but that's OK)
643
+ try {
644
+ const validation = await oxyServices.validateSession(storedActiveSessionId, { useHeaderValidation: false });
645
+ if (validation?.valid && validation.user) {
646
+ loginSuccess(validation.user);
647
+ }
648
+ } catch {
649
+ // Ignore - we're offline, will sync when online
650
+ }
651
+ }
652
+ }
634
653
  if (__DEV__) {
635
654
  loggerUtil.debug('Active session validation timeout (expected when offline)', { component: 'OxyContext', method: 'restoreSessionsFromStorage' }, switchError as unknown);
636
655
  }
@@ -639,6 +658,26 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
639
658
  logger('Active session validation error', switchError);
640
659
  }
641
660
  }
661
+ } else if (validSessions.length > 0) {
662
+ // No stored active session, but we have valid sessions - activate the first one
663
+ const firstSession = validSessions[0];
664
+ try {
665
+ await switchSession(firstSession.sessionId);
666
+ } catch (switchError) {
667
+ // If switch fails, at least set the activeSessionId so UI can show sessions
668
+ if (isTimeoutOrNetworkError(switchError)) {
669
+ setActiveSessionIdFromHook(firstSession.sessionId);
670
+ // Try to get user from session
671
+ try {
672
+ const validation = await oxyServices.validateSession(firstSession.sessionId, { useHeaderValidation: false });
673
+ if (validation?.valid && validation.user) {
674
+ loginSuccess(validation.user);
675
+ }
676
+ } catch {
677
+ // Ignore - offline scenario
678
+ }
679
+ }
680
+ }
642
681
  }
643
682
  } catch (error) {
644
683
  if (__DEV__) {
@@ -657,6 +696,8 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
657
696
  storageKeys.sessionIds,
658
697
  switchSession,
659
698
  updateSessions,
699
+ setActiveSessionIdFromHook,
700
+ loginSuccess,
660
701
  ]);
661
702
 
662
703
  useEffect(() => {
@@ -673,6 +714,18 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
673
714
  : undefined;
674
715
  const currentDeviceId = activeSession?.deviceId ?? null;
675
716
 
717
+ // Compute isAuthenticated from actual session state, not just auth store
718
+ // This ensures UI shows correct state even if loginSuccess wasn't called during restoration
719
+ const isAuthenticatedFromSessions = useMemo(() => {
720
+ return !!(activeSessionId && sessions.length > 0 && user);
721
+ }, [activeSessionId, sessions.length, user]);
722
+
723
+ // Use session-based authentication state if auth store says not authenticated but we have sessions
724
+ // This handles the case where sessions were restored but loginSuccess wasn't called
725
+ const computedIsAuthenticated = useMemo(() => {
726
+ return isAuthenticatedFromStore || isAuthenticatedFromSessions;
727
+ }, [isAuthenticatedFromStore, isAuthenticatedFromSessions]);
728
+
676
729
  // Get userId from JWT token (MongoDB ObjectId) for socket room matching
677
730
  // user.id is set to publicKey for compatibility, but socket rooms use MongoDB ObjectId
678
731
  // The JWT token's userId field contains the MongoDB ObjectId
@@ -801,8 +854,9 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
801
854
  }, [logger, logout]);
802
855
 
803
856
  // Check pending transfers when authenticated and online using TanStack Query
804
- // Pass oxyServices and isAuthenticated directly to avoid circular dependency
805
- const { data: pendingTransferResults } = useCheckPendingTransfers(oxyServices, isAuthenticated);
857
+ // Check for pending transfers that may have completed while offline
858
+ // Results are processed via socket events (onIdentityTransferComplete), so we don't need to process query results here
859
+ useCheckPendingTransfers(oxyServices, computedIsAuthenticated);
806
860
 
807
861
  const handleIdentityTransferComplete = useCallback(
808
862
  async (data: { transferId: string; sourceDeviceId: string; publicKey: string; transferCode?: string; completedAt: string }) => {
@@ -1023,7 +1077,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1023
1077
  sessions,
1024
1078
  activeSessionId,
1025
1079
  currentDeviceId,
1026
- isAuthenticated,
1080
+ isAuthenticated: computedIsAuthenticated,
1027
1081
  isLoading,
1028
1082
  isTokenReady: tokenReady,
1029
1083
  isStorageReady,
@@ -1090,7 +1144,7 @@ export const OxyProvider: React.FC<OxyContextProviderProps> = ({
1090
1144
  currentNativeLanguageName,
1091
1145
  error,
1092
1146
  getDeviceSessions,
1093
- isAuthenticated,
1147
+ computedIsAuthenticated,
1094
1148
  isLoading,
1095
1149
  logout,
1096
1150
  logoutAll,
@@ -1,5 +1,4 @@
1
- import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
2
- import { useOxy } from '../context/OxyContext';
1
+ import { useQuery } from '@tanstack/react-query';
3
2
  import { useTransferStore } from '../stores/transferStore';
4
3
  import type { OxyServices } from '../../core';
5
4
 
@@ -7,66 +6,9 @@ import type { OxyServices } from '../../core';
7
6
  * Query keys for transfer-related queries
8
7
  */
9
8
  export const transferQueryKeys = {
10
- all: ['transfers'] as const,
11
- completion: (transferId: string) => ['transfers', 'completion', transferId] as const,
12
9
  pending: () => ['transfers', 'pending'] as const,
13
10
  };
14
11
 
15
- /**
16
- * Hook to check if a transfer was completed
17
- * Only runs when authenticated and transferId is provided
18
- */
19
- export const useCheckTransferCompletion = (transferId: string | null, enabled: boolean = true) => {
20
- const { oxyServices, isAuthenticated } = useOxy();
21
-
22
- return useQuery({
23
- queryKey: transferId ? transferQueryKeys.completion(transferId) : ['transfers', 'completion', 'null'],
24
- queryFn: async () => {
25
- if (!transferId || !oxyServices) {
26
- return null;
27
- }
28
-
29
- try {
30
- const response = await oxyServices.makeRequest<{
31
- completed: boolean;
32
- transferId?: string;
33
- sourceDeviceId?: string;
34
- publicKey?: string;
35
- transferCode?: string;
36
- completedAt?: string;
37
- }>(
38
- 'GET',
39
- `/api/identity/check-transfer/${transferId}`,
40
- undefined,
41
- { cache: false }
42
- );
43
-
44
- return response;
45
- } catch (error: any) {
46
- // Handle 401 errors gracefully - don't throw, just return null
47
- if (error?.status === 401 || error?.message?.includes('401') || error?.message?.includes('authentication')) {
48
- if (__DEV__) {
49
- console.warn('[useCheckTransferCompletion] Authentication required, skipping check');
50
- }
51
- return null;
52
- }
53
- throw error;
54
- }
55
- },
56
- enabled: enabled && !!transferId && isAuthenticated && !!oxyServices,
57
- staleTime: 30 * 1000, // 30 seconds - completion status doesn't change frequently
58
- gcTime: 5 * 60 * 1000, // 5 minutes
59
- retry: (failureCount, error: any) => {
60
- // Don't retry on 401 errors
61
- if (error?.status === 401 || error?.message?.includes('401')) {
62
- return false;
63
- }
64
- return failureCount < 2;
65
- },
66
- retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 5000),
67
- });
68
- };
69
-
70
12
  /**
71
13
  * Hook to check all pending transfers for completion
72
14
  * Used when app comes back online
@@ -158,11 +100,3 @@ export const useCheckPendingTransfers = (
158
100
  });
159
101
  };
160
102
 
161
- /**
162
- * Hook version that uses useOxy() - for use outside OxyContext
163
- */
164
- export const useCheckPendingTransfersWithContext = () => {
165
- const { oxyServices, isAuthenticated } = useOxy();
166
- return useCheckPendingTransfers(oxyServices, isAuthenticated);
167
- };
168
-
@@ -192,10 +192,4 @@ export const useTransferCodesForPersistence = () => {
192
192
  );
193
193
  };
194
194
 
195
- /**
196
- * Hook to check if store has been restored
197
- */
198
- export const useTransferStoreRestored = () => {
199
- return useTransferStore((state) => state.isRestored);
200
- };
201
195