@oxyhq/services 5.17.5 → 5.17.8

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 (54) hide show
  1. package/lib/commonjs/crypto/keyManager.js +6 -161
  2. package/lib/commonjs/crypto/keyManager.js.map +1 -1
  3. package/lib/commonjs/ui/context/OxyContext.js +20 -543
  4. package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
  5. package/lib/commonjs/ui/context/OxyContextBase.js.map +1 -1
  6. package/lib/commonjs/ui/context/hooks/useAuthOperations.js +14 -331
  7. package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
  8. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +8 -112
  9. package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  10. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +2 -27
  11. package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
  12. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js +2 -27
  13. package/lib/commonjs/ui/hooks/queries/useServicesQueries.js.map +1 -1
  14. package/lib/commonjs/ui/hooks/useSessionSocket.js +2 -88
  15. package/lib/commonjs/ui/hooks/useSessionSocket.js.map +1 -1
  16. package/lib/module/crypto/keyManager.js +6 -161
  17. package/lib/module/crypto/keyManager.js.map +1 -1
  18. package/lib/module/ui/context/OxyContext.js +20 -543
  19. package/lib/module/ui/context/OxyContext.js.map +1 -1
  20. package/lib/module/ui/context/OxyContextBase.js.map +1 -1
  21. package/lib/module/ui/context/hooks/useAuthOperations.js +14 -330
  22. package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
  23. package/lib/module/ui/hooks/mutations/useAccountMutations.js +8 -112
  24. package/lib/module/ui/hooks/mutations/useAccountMutations.js.map +1 -1
  25. package/lib/module/ui/hooks/queries/useAccountQueries.js +2 -27
  26. package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
  27. package/lib/module/ui/hooks/queries/useServicesQueries.js +2 -27
  28. package/lib/module/ui/hooks/queries/useServicesQueries.js.map +1 -1
  29. package/lib/module/ui/hooks/useSessionSocket.js +2 -88
  30. package/lib/module/ui/hooks/useSessionSocket.js.map +1 -1
  31. package/lib/typescript/crypto/keyManager.d.ts +3 -20
  32. package/lib/typescript/crypto/keyManager.d.ts.map +1 -1
  33. package/lib/typescript/crypto/types.d.ts +4 -0
  34. package/lib/typescript/crypto/types.d.ts.map +1 -1
  35. package/lib/typescript/ui/context/OxyContext.d.ts.map +1 -1
  36. package/lib/typescript/ui/context/OxyContextBase.d.ts +0 -37
  37. package/lib/typescript/ui/context/OxyContextBase.d.ts.map +1 -1
  38. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts +1 -20
  39. package/lib/typescript/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
  40. package/lib/typescript/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
  41. package/lib/typescript/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
  42. package/lib/typescript/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
  43. package/lib/typescript/ui/hooks/useSessionSocket.d.ts +1 -14
  44. package/lib/typescript/ui/hooks/useSessionSocket.d.ts.map +1 -1
  45. package/package.json +1 -1
  46. package/src/crypto/keyManager.ts +4 -170
  47. package/src/crypto/types.ts +4 -0
  48. package/src/ui/context/OxyContext.tsx +17 -588
  49. package/src/ui/context/OxyContextBase.tsx +2 -20
  50. package/src/ui/context/hooks/useAuthOperations.ts +22 -347
  51. package/src/ui/hooks/mutations/useAccountMutations.ts +12 -110
  52. package/src/ui/hooks/queries/useAccountQueries.ts +3 -27
  53. package/src/ui/hooks/queries/useServicesQueries.ts +3 -27
  54. package/src/ui/hooks/useSessionSocket.ts +2 -106
@@ -23,27 +23,9 @@ export interface OxyContextState {
23
23
  currentLanguageName: string;
24
24
  currentNativeLanguageName: string;
25
25
 
26
- // Identity management (public key authentication - offline-first)
27
- createIdentity: () => Promise<{ synced: boolean }>;
28
- importIdentity: (backupData: BackupData, password: string) => Promise<{ synced: boolean }>;
26
+ // Authentication (Services SDK only handles tokens/sessions, NOT identity)
27
+ // Identity management (createIdentity, importIdentity, etc.) belongs in Accounts app
29
28
  signIn: (deviceName?: string) => Promise<User>;
30
- hasIdentity: () => Promise<boolean>;
31
- getPublicKey: () => Promise<string | null>;
32
- isIdentitySynced: () => Promise<boolean>;
33
- syncIdentity: () => Promise<User>;
34
- deleteIdentityAndClearAccount: (skipBackup?: boolean, force?: boolean, userConfirmed?: boolean) => Promise<void>;
35
- storeTransferCode: (transferId: string, code: string, sourceDeviceId: string | null, publicKey: string) => Promise<void>;
36
- getTransferCode: (transferId: string) => { code: string; sourceDeviceId: string | null; publicKey: string; timestamp: number; state: 'pending' | 'completed' | 'failed' } | null;
37
- clearTransferCode: (transferId: string) => Promise<void>;
38
- getAllPendingTransfers: () => Array<{ transferId: string; data: { code: string; sourceDeviceId: string | null; publicKey: string; timestamp: number; state: 'pending' | 'completed' | 'failed' } }>;
39
- getActiveTransferId: () => string | null;
40
- updateTransferState: (transferId: string, state: 'pending' | 'completed' | 'failed') => Promise<void>;
41
-
42
- // Identity sync state (reactive, from Zustand store)
43
- identitySyncState: {
44
- isSynced: boolean;
45
- isSyncing: boolean;
46
- };
47
29
 
48
30
  // Session management
49
31
  logout: (targetSessionId?: string) => Promise<void>;
@@ -1,13 +1,13 @@
1
1
  import { useCallback } from 'react';
2
2
  import type { ApiError, User } from '../../../models/interfaces';
3
3
  import type { AuthState } from '../../stores/authStore';
4
- import type { ClientSession, SessionLoginResponse } from '../../../models/session';
4
+ import type { ClientSession } from '../../../models/session';
5
5
  import { DeviceManager } from '../../../utils/deviceManager';
6
- import { fetchSessionsWithFallback, mapSessionsToClient } from '../../utils/sessionHelpers';
6
+ import { fetchSessionsWithFallback } from '../../utils/sessionHelpers';
7
7
  import { handleAuthError, isInvalidSessionError } from '../../utils/errorHandlers';
8
8
  import type { StorageInterface } from '../../utils/storageHelpers';
9
9
  import type { OxyServices } from '../../../core';
10
- import { KeyManager, SignatureService, type BackupData } from '../../../crypto';
10
+ import { KeyManager, SignatureService } from '../../../crypto';
11
11
 
12
12
  export interface UseAuthOperationsOptions {
13
13
  oxyServices: OxyServices;
@@ -26,38 +26,23 @@ export interface UseAuthOperationsOptions {
26
26
  loginFailure: (message: string) => void;
27
27
  logoutStore: () => void;
28
28
  setAuthState: (state: Partial<AuthState>) => void;
29
- // Identity sync store actions
30
- setIdentitySynced: (synced: boolean) => void;
31
- setSyncing: (syncing: boolean) => void;
32
29
  logger?: (message: string, error?: unknown) => void;
33
30
  }
34
31
 
35
32
  export interface UseAuthOperationsResult {
36
- /** Create a new identity locally (offline-first) and optionally sync with server */
37
- createIdentity: () => Promise<{ synced: boolean }>;
38
- /** Import an existing identity from backup file data */
39
- importIdentity: (backupData: BackupData, password: string) => Promise<{ synced: boolean }>;
40
33
  /** Sign in with existing identity on device */
41
34
  signIn: (deviceName?: string) => Promise<User>;
42
35
  /** Logout from current session */
43
36
  logout: (targetSessionId?: string) => Promise<void>;
44
37
  /** Logout from all sessions */
45
38
  logoutAll: () => Promise<void>;
46
- /** Check if device has an identity stored */
47
- hasIdentity: () => Promise<boolean>;
48
- /** Get the public key of the stored identity */
49
- getPublicKey: () => Promise<string | null>;
50
- /** Check if identity is synced with server */
51
- isIdentitySynced: () => Promise<boolean>;
52
- /** Sync local identity with server (when online) */
53
- syncIdentity: () => Promise<User>;
54
39
  }
55
40
 
56
41
  const LOGIN_ERROR_CODE = 'LOGIN_ERROR';
57
- const REGISTER_ERROR_CODE = 'REGISTER_ERROR';
58
42
  const LOGOUT_ERROR_CODE = 'LOGOUT_ERROR';
59
43
  const LOGOUT_ALL_ERROR_CODE = 'LOGOUT_ALL_ERROR';
60
44
 
45
+
61
46
  /**
62
47
  * Authentication operations using public key cryptography.
63
48
  * No passwords required - identity is based on ECDSA key pairs.
@@ -78,54 +63,33 @@ export const useAuthOperations = ({
78
63
  loginSuccess,
79
64
  loginFailure,
80
65
  logoutStore,
81
- setAuthState,
82
- setIdentitySynced,
83
- setSyncing,
84
- logger,
66
+ setAuthState,
67
+ logger,
85
68
  }: UseAuthOperationsOptions): UseAuthOperationsResult => {
86
69
 
87
70
  /**
88
- * Internal function to perform challenge-response sign in (works offline)
71
+ * Internal function to perform challenge-response sign in
89
72
  */
90
73
  const performSignIn = useCallback(
91
- async (publicKey: string): Promise<User> => {
74
+ async (publicKey: string, deviceName?: string): Promise<User> => {
92
75
  const deviceFingerprintObj = DeviceManager.getDeviceFingerprint();
93
76
  const deviceFingerprint = JSON.stringify(deviceFingerprintObj);
94
77
  const deviceInfo = await DeviceManager.getDeviceInfo();
95
- const deviceName = deviceInfo.deviceName || DeviceManager.getDefaultDeviceName();
96
- const USER_ID_STORAGE_KEY = 'oxy_user_id';
97
-
98
- // Online-only sign-in: require backend availability
99
- // First, look up the user by public key to get the correct userId
100
- // This ensures we always use the userId that matches the current identity's public key
101
- let userId: string | null = null;
102
-
103
- // Always verify the userId matches the current public key
104
- // This prevents auth failures when identity has changed
78
+ const defaultDeviceName = deviceInfo.deviceName || DeviceManager.getDefaultDeviceName();
79
+ const finalDeviceName = deviceName || defaultDeviceName;
80
+
81
+ // Look up user by public key
105
82
  const userLookup = await oxyServices.getUserByPublicKey(publicKey);
106
- userId = userLookup.id;
107
-
108
- // Update stored userId to match current identity
109
- if (storage && userId) {
110
- await storage.setItem(USER_ID_STORAGE_KEY, userId).catch(() => {});
111
- }
112
-
83
+ const userId = userLookup.id;
84
+
85
+ // Request challenge
113
86
  const challengeResponse = await oxyServices.requestChallenge(userId);
114
87
  const challenge = challengeResponse.challenge;
115
88
 
116
- // Note: Biometric authentication check should be handled by the app layer
117
- // (e.g., accounts app) before calling signIn. The biometric preference is stored
118
- // in local storage as 'oxy_biometric_enabled' and can be checked there.
119
-
120
89
  // Sign the challenge
121
90
  const { challenge: signature, timestamp } = await SignatureService.signChallenge(challenge);
122
91
 
123
- // Online sign-in: use normal flow
124
- if (!userId) {
125
- throw new Error('User ID not found');
126
- }
127
-
128
- // Verify and create session using userId
92
+ // Verify and create session
129
93
  let sessionResponse;
130
94
  try {
131
95
  sessionResponse = await oxyServices.verifyChallenge(
@@ -133,11 +97,10 @@ export const useAuthOperations = ({
133
97
  challenge,
134
98
  signature,
135
99
  timestamp,
136
- deviceName,
100
+ finalDeviceName,
137
101
  deviceFingerprint,
138
102
  );
139
103
  } catch (verifyError) {
140
- // Add detailed logging for 401 errors to help diagnose auth failures
141
104
  if (__DEV__) {
142
105
  console.error('[useAuthOperations] verifyChallenge failed:', {
143
106
  error: verifyError,
@@ -151,24 +114,11 @@ export const useAuthOperations = ({
151
114
  throw verifyError;
152
115
  }
153
116
 
154
- // Store tokens immediately (no extra round-trip)
117
+ // Store tokens
155
118
  oxyServices.setTokens(sessionResponse.accessToken, sessionResponse.refreshToken);
156
119
 
157
120
  // Get full user data
158
121
  const fullUser = await oxyServices.getUserBySession(sessionResponse.sessionId);
159
-
160
- // IMPORTANT: user.id should be MongoDB ObjectId, not publicKey
161
- // The API should return the correct id (ObjectId) from the database
162
- // If it doesn't, we need to fix the API, not work around it here
163
- // Validate that id is ObjectId format (24 hex characters)
164
- if (fullUser.id && !/^[0-9a-fA-F]{24}$/.test(fullUser.id)) {
165
- console.warn('[useAuthOperations] User.id is not MongoDB ObjectId format:', {
166
- id: fullUser.id.substring(0, 20),
167
- publicKey: fullUser.publicKey.substring(0, 20),
168
- message: 'API should return MongoDB ObjectId as user.id, not publicKey'
169
- });
170
- // Don't override - let the API fix this issue
171
- }
172
122
 
173
123
  // Fetch device sessions
174
124
  let allDeviceSessions: ClientSession[] = [];
@@ -214,13 +164,9 @@ export const useAuthOperations = ({
214
164
  updateSessions(allDeviceSessions, { merge: true });
215
165
 
216
166
  await applyLanguagePreference(fullUser);
217
- loginSuccess(); // Services never caches profile - only tokens
167
+ loginSuccess();
218
168
  onAuthStateChange?.(fullUser);
219
- if (storage) {
220
- await storage.setItem('oxy_identity_synced', 'true').catch(() => {});
221
- }
222
- setIdentitySynced(true);
223
-
169
+
224
170
  return fullUser;
225
171
  },
226
172
  [
@@ -231,263 +177,11 @@ export const useAuthOperations = ({
231
177
  oxyServices,
232
178
  saveActiveSessionId,
233
179
  setActiveSessionId,
234
- setIdentitySynced,
235
180
  switchSession,
236
181
  updateSessions,
237
- storage,
238
182
  ],
239
183
  );
240
184
 
241
- /**
242
- * Create a new identity (offline-first)
243
- * Identity is purely cryptographic - no username or email required
244
- */
245
- const createIdentity = useCallback(
246
- async (): Promise<{ synced: boolean }> => {
247
- if (!storage) throw new Error('Storage not initialized');
248
-
249
- setAuthState({ isLoading: true, error: null });
250
-
251
- try {
252
- // Generate new key pair directly (works offline)
253
- const { publicKey, privateKey } = await KeyManager.generateKeyPair();
254
- await KeyManager.importKeyPair(privateKey);
255
-
256
- // Mark as not synced
257
- // Note: createIdentity only creates the key locally (offline-first)
258
- // Registration with server (registerIdentity) must be done by the app (Accounts) with profile data
259
- await storage.setItem('oxy_identity_synced', 'false');
260
- setIdentitySynced(false);
261
-
262
- return {
263
- synced: false, // Always false - registration must be done separately by Accounts app
264
- };
265
- } catch (error) {
266
- // CRITICAL: Never delete identity on error - it may have been successfully created
267
- // Only log the error and let the user recover using their backup file
268
- // Identity deletion should ONLY happen when explicitly requested by the user
269
- if (__DEV__ && logger) {
270
- logger('Error during identity creation (identity may still exist):', error);
271
- }
272
-
273
- // Check if identity was actually created (keys exist)
274
- const hasIdentity = await KeyManager.hasIdentity().catch(() => false);
275
- if (hasIdentity) {
276
- // Identity exists - don't delete it! Just mark as not synced
277
- await storage.setItem('oxy_identity_synced', 'false').catch(() => {});
278
- setIdentitySynced(false);
279
- if (__DEV__ && logger) {
280
- logger('Identity was created but sync failed - user can sync later using backup file');
281
- }
282
- } else {
283
- // No identity exists - this was a generation failure, safe to clean up sync flag
284
- await storage.removeItem('oxy_identity_synced').catch(() => {});
285
- setIdentitySynced(false);
286
- }
287
-
288
- const message = handleAuthError(error, {
289
- defaultMessage: 'Failed to create identity',
290
- code: REGISTER_ERROR_CODE,
291
- onError,
292
- setAuthError: (msg: string) => setAuthState({ error: msg }),
293
- logger,
294
- });
295
- loginFailure(message);
296
- throw error;
297
- } finally {
298
- setAuthState({ isLoading: false });
299
- }
300
- },
301
- [oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced],
302
- );
303
-
304
- /**
305
- * Check if identity is synced with server (reads from storage for persistence)
306
- */
307
- const isIdentitySyncedFn = useCallback(async (): Promise<boolean> => {
308
- if (!storage) return true;
309
- const synced = await storage.getItem('oxy_identity_synced');
310
- const isSynced = synced !== 'false';
311
- setIdentitySynced(isSynced);
312
- return isSynced;
313
- }, [storage, setIdentitySynced]);
314
-
315
- /**
316
- * Sync local identity with server (call when online)
317
- * TanStack Query handles offline mutations automatically
318
- */
319
- const syncIdentity = useCallback(
320
- async (): Promise<User> => {
321
- if (!storage) throw new Error('Storage not initialized');
322
-
323
- setAuthState({ isLoading: true, error: null });
324
- setSyncing(true);
325
-
326
- try {
327
- const publicKey = await KeyManager.getPublicKey();
328
- if (!publicKey) {
329
- throw new Error('No identity found on this device');
330
- }
331
-
332
- // Check if already synced
333
- const alreadySynced = await storage.getItem('oxy_identity_synced');
334
- if (alreadySynced === 'true') {
335
- setIdentitySynced(true);
336
- return await performSignIn(publicKey);
337
- }
338
-
339
- // Check if already registered on server
340
- const { registered } = await oxyServices.checkPublicKeyRegistered(publicKey);
341
-
342
- if (!registered) {
343
- // Identity is not registered - registration must be done by Accounts app with profile data
344
- // syncIdentity only syncs already-registered identities
345
- throw new Error('Identity is not registered. Please register your identity first using the Accounts app.');
346
- }
347
-
348
- // Mark as synced (Zustand store + storage)
349
- await storage.setItem('oxy_identity_synced', 'true');
350
- setIdentitySynced(true);
351
-
352
- // Sign in (Services never caches profile - only tokens)
353
- const user = await performSignIn(publicKey);
354
-
355
- // Check if user has username - required for syncing
356
- if (!user.username) {
357
- const usernameError = new Error('USERNAME_REQUIRED');
358
- (usernameError as any).code = 'USERNAME_REQUIRED';
359
- throw usernameError;
360
- }
361
-
362
- // TanStack Query will automatically retry any pending mutations
363
-
364
- return user;
365
- } catch (error) {
366
- const message = handleAuthError(error, {
367
- defaultMessage: 'Failed to sync identity',
368
- code: REGISTER_ERROR_CODE,
369
- onError,
370
- setAuthError: (msg: string) => setAuthState({ error: msg }),
371
- logger,
372
- });
373
- loginFailure(message);
374
- throw error;
375
- } finally {
376
- setAuthState({ isLoading: false });
377
- setSyncing(false);
378
- }
379
- },
380
- [oxyServices, storage, setAuthState, performSignIn, loginFailure, onError, logger, setSyncing, setIdentitySynced],
381
- );
382
-
383
- /**
384
- * Import identity from backup file data (offline-first)
385
- */
386
- const importIdentity = useCallback(
387
- async (backupData: BackupData, password: string): Promise<{ synced: boolean }> => {
388
- if (!storage) throw new Error('Storage not initialized');
389
-
390
- // Validate arguments - ensure backupData is an object, not a string (old signature)
391
- if (!backupData || typeof backupData !== 'object' || Array.isArray(backupData)) {
392
- throw new Error('Invalid backup data. Please use the backup file import feature.');
393
- }
394
-
395
- if (!backupData.encrypted || !backupData.salt || !backupData.iv || !backupData.publicKey) {
396
- throw new Error('Invalid backup data structure. Missing required fields.');
397
- }
398
-
399
- if (!password || typeof password !== 'string') {
400
- throw new Error('Password is required for backup file import.');
401
- }
402
-
403
- setAuthState({ isLoading: true, error: null });
404
-
405
- try {
406
- // Decrypt private key from backup data
407
- const Crypto = await import('expo-crypto');
408
-
409
- // Convert hex strings to Uint8Array
410
- const saltBytes = new Uint8Array(
411
- backupData.salt.match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || []
412
- );
413
- const ivBytes = new Uint8Array(
414
- backupData.iv.match(/.{1,2}/g)?.map(byte => parseInt(byte, 16)) || []
415
- );
416
-
417
- // Derive key from password (same algorithm as EncryptedBackupGenerator)
418
- const saltHex = Array.from(saltBytes).map(b => b.toString(16).padStart(2, '0')).join('');
419
- let key = password + saltHex;
420
- for (let i = 0; i < 10000; i++) {
421
- key = await Crypto.digestStringAsync(
422
- Crypto.CryptoDigestAlgorithm.SHA256,
423
- key
424
- );
425
- }
426
- const keyBytes = new Uint8Array(32);
427
- for (let i = 0; i < 64 && i < key.length; i += 2) {
428
- keyBytes[i / 2] = parseInt(key.substring(i, i + 2), 16);
429
- }
430
-
431
- // Decrypt private key (XOR decryption - same as encryption)
432
- const encryptedBytes = Buffer.from(backupData.encrypted, 'base64');
433
- const decryptedBytes = new Uint8Array(encryptedBytes.length);
434
- for (let i = 0; i < encryptedBytes.length; i++) {
435
- decryptedBytes[i] = encryptedBytes[i] ^ keyBytes[i % keyBytes.length] ^ ivBytes[i % ivBytes.length];
436
- }
437
- const privateKey = new TextDecoder().decode(decryptedBytes);
438
-
439
- // Import the key pair
440
- const publicKey = await KeyManager.importKeyPair(privateKey);
441
-
442
- // Verify public key matches
443
- if (publicKey !== backupData.publicKey) {
444
- throw new Error('Backup file is corrupted or password is incorrect');
445
- }
446
-
447
- // Mark as not synced
448
- await storage.setItem('oxy_identity_synced', 'false');
449
- setIdentitySynced(false);
450
-
451
- // Try to sync with server
452
- try {
453
- // Check if this identity is already registered
454
- const { registered } = await oxyServices.checkPublicKeyRegistered(publicKey);
455
-
456
- if (registered) {
457
- // Identity exists, mark as synced
458
- await storage.setItem('oxy_identity_synced', 'true');
459
- setIdentitySynced(true);
460
- return { synced: true };
461
- } else {
462
- // Identity is not registered - registration must be done by Accounts app with profile data
463
- // importIdentity only imports already-registered identities
464
- await storage.setItem('oxy_identity_synced', 'false');
465
- setIdentitySynced(false);
466
- return { synced: false };
467
- }
468
- } catch (syncError) {
469
- // Offline - identity restored locally but not synced
470
- if (__DEV__) {
471
- console.log('[Auth] Identity imported locally, will sync when online:', syncError);
472
- }
473
- return { synced: false };
474
- }
475
- } catch (error) {
476
- const message = handleAuthError(error, {
477
- defaultMessage: 'Failed to import identity. Please check your password and backup file.',
478
- code: REGISTER_ERROR_CODE,
479
- onError,
480
- setAuthError: (msg: string) => setAuthState({ error: msg }),
481
- logger,
482
- });
483
- loginFailure(message);
484
- throw error;
485
- } finally {
486
- setAuthState({ isLoading: false });
487
- }
488
- },
489
- [oxyServices, storage, setAuthState, loginFailure, onError, logger, setIdentitySynced],
490
- );
491
185
 
492
186
  /**
493
187
  * Sign in with existing identity on device
@@ -511,7 +205,7 @@ export const useAuthOperations = ({
511
205
  throw new Error('Identity is not registered. Please register your identity in the Accounts app before signing in.');
512
206
  }
513
207
 
514
- return await performSignIn(publicKey);
208
+ return await performSignIn(publicKey, deviceName);
515
209
  } catch (error) {
516
210
  const message = handleAuthError(error, {
517
211
  defaultMessage: 'Sign in failed',
@@ -529,6 +223,7 @@ export const useAuthOperations = ({
529
223
  [storage, setAuthState, performSignIn, loginFailure, onError, logger, oxyServices],
530
224
  );
531
225
 
226
+
532
227
  /**
533
228
  * Logout from session
534
229
  */
@@ -608,29 +303,9 @@ export const useAuthOperations = ({
608
303
  }
609
304
  }, [activeSessionId, clearSessionState, logger, onError, oxyServices, setAuthState]);
610
305
 
611
- /**
612
- * Check if device has an identity stored
613
- */
614
- const hasIdentity = useCallback(async (): Promise<boolean> => {
615
- return KeyManager.hasIdentity();
616
- }, []);
617
-
618
- /**
619
- * Get the public key of the stored identity
620
- */
621
- const getPublicKey = useCallback(async (): Promise<string | null> => {
622
- return KeyManager.getPublicKey();
623
- }, []);
624
-
625
306
  return {
626
- createIdentity,
627
- importIdentity,
628
307
  signIn,
629
308
  logout,
630
309
  logoutAll,
631
- hasIdentity,
632
- getPublicKey,
633
- isIdentitySynced: isIdentitySyncedFn,
634
- syncIdentity,
635
310
  };
636
311
  };