@explorins/pers-sdk-react-native 1.5.18 → 1.5.20

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 (40) hide show
  1. package/README.md +336 -234
  2. package/dist/hooks/index.d.ts +1 -1
  3. package/dist/hooks/index.d.ts.map +1 -1
  4. package/dist/hooks/useAuth.d.ts +1 -1
  5. package/dist/hooks/useAuth.d.ts.map +1 -1
  6. package/dist/hooks/useAuth.js +7 -7
  7. package/dist/hooks/useRedemptions.d.ts.map +1 -1
  8. package/dist/hooks/useRedemptions.js +4 -4
  9. package/dist/hooks/useTenants.d.ts.map +1 -1
  10. package/dist/hooks/useTenants.js +0 -1
  11. package/dist/hooks/useTransactionSigner.d.ts +186 -53
  12. package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
  13. package/dist/hooks/useTransactionSigner.js +285 -102
  14. package/dist/hooks/useTransactions.d.ts +2 -2
  15. package/dist/hooks/useTransactions.d.ts.map +1 -1
  16. package/dist/hooks/useTransactions.js +9 -10
  17. package/dist/index.d.ts +211 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +20918 -18336
  20. package/dist/index.js.map +1 -1
  21. package/dist/providers/PersSDKProvider.d.ts +2 -8
  22. package/dist/providers/PersSDKProvider.d.ts.map +1 -1
  23. package/dist/providers/PersSDKProvider.js +16 -31
  24. package/dist/providers/react-native-auth-provider.d.ts +25 -36
  25. package/dist/providers/react-native-auth-provider.d.ts.map +1 -1
  26. package/dist/providers/react-native-auth-provider.js +36 -146
  27. package/dist/storage/async-storage-token-storage.d.ts +22 -0
  28. package/dist/storage/async-storage-token-storage.d.ts.map +1 -0
  29. package/dist/storage/async-storage-token-storage.js +113 -0
  30. package/package.json +16 -11
  31. package/src/hooks/index.ts +1 -1
  32. package/src/hooks/useAuth.ts +7 -7
  33. package/src/hooks/useRedemptions.ts +5 -7
  34. package/src/hooks/useTenants.ts +0 -1
  35. package/src/hooks/useTransactionSigner.ts +322 -166
  36. package/src/hooks/useTransactions.ts +12 -11
  37. package/src/index.ts +243 -7
  38. package/src/providers/PersSDKProvider.tsx +21 -40
  39. package/src/providers/react-native-auth-provider.ts +59 -176
  40. package/src/storage/async-storage-token-storage.ts +133 -0
@@ -1,6 +1,5 @@
1
1
  import React, { ReactNode } from 'react';
2
- import { PersSDK, PersConfig } from '@explorins/pers-sdk/core';
3
- import { ReactNativeAuthProvider } from './react-native-auth-provider';
2
+ import { PersSDK, PersConfig, DefaultAuthProvider } from '@explorins/pers-sdk/core';
4
3
  import { UserDTO, AdminDTO } from '@explorins/pers-shared';
5
4
  import type { AuthManager, UserManager, TokenManager, BusinessManager, CampaignManager, RedemptionManager, TransactionManager, PurchaseManager, TenantManager, AnalyticsManager, DonationManager } from '@explorins/pers-sdk/core';
6
5
  export type { PersConfig } from '@explorins/pers-sdk/core';
@@ -18,7 +17,7 @@ export interface PersSDKContext {
18
17
  analytics: AnalyticsManager | null;
19
18
  donations: DonationManager | null;
20
19
  business: BusinessManager | null;
21
- authProvider: ReactNativeSDKAuthProvider | null;
20
+ authProvider: DefaultAuthProvider | null;
22
21
  isInitialized: boolean;
23
22
  isAuthenticated: boolean;
24
23
  user: UserDTO | AdminDTO | null;
@@ -27,11 +26,6 @@ export interface PersSDKContext {
27
26
  setAuthenticationState: (user: UserDTO | AdminDTO | null, accountAddress: string | null, isAuthenticated: boolean) => void;
28
27
  refreshUserData: () => Promise<void>;
29
28
  }
30
- declare class ReactNativeSDKAuthProvider extends ReactNativeAuthProvider {
31
- constructor(projectKey: string);
32
- setToken(token: string | null): Promise<void>;
33
- getToken(): Promise<string | null>;
34
- }
35
29
  export declare const PersSDKProvider: React.FC<{
36
30
  children: ReactNode;
37
31
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAAuB,MAAM,OAAO,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,UAAU,EAAsB,MAAM,0BAA0B,CAAC;AAEnF,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAGlC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IAGjC,YAAY,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAGhD,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3H,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAMD,cAAM,0BAA2B,SAAQ,uBAAuB;gBAClD,UAAU,EAAE,MAAM;IAKxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7C,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;CAGzC;AAGD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;CACrB,CAgHA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
1
+ {"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAAuB,MAAM,OAAO,CAAC;AACnG,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAGpF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAG3D,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,WAAW,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACtC,YAAY,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACxC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAGlC,QAAQ,EAAE,eAAe,GAAG,IAAI,CAAC;IAGjC,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGzC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAG9B,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3H,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAMD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;CACrB,CAkHA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
@@ -2,28 +2,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useState, useCallback, useRef } from 'react';
3
3
  import { PersSDK } from '@explorins/pers-sdk/core';
4
4
  import { ReactNativeHttpClient } from './react-native-http-client';
5
- import { ReactNativeAuthProvider } from './react-native-auth-provider';
5
+ import { createReactNativeAuthProvider } from './react-native-auth-provider';
6
6
  // Create the context
7
7
  const SDKContext = createContext(null);
8
- // Simple wrapper for SDK integration
9
- class ReactNativeSDKAuthProvider extends ReactNativeAuthProvider {
10
- constructor(projectKey) {
11
- super(projectKey, { debug: true });
12
- }
13
- // Override setAccessToken to provide backward compatibility
14
- async setToken(token) {
15
- if (token) {
16
- await this.setAccessToken(token);
17
- }
18
- else {
19
- await this.clearTokens();
20
- }
21
- }
22
- // Override getToken for backward compatibility
23
- async getToken() {
24
- return await super.getToken();
25
- }
26
- }
27
8
  // Provider component
28
9
  export const PersSDKProvider = ({ children }) => {
29
10
  const initializingRef = useRef(false);
@@ -36,27 +17,33 @@ export const PersSDKProvider = ({ children }) => {
36
17
  const initialize = useCallback(async (config) => {
37
18
  // Prevent multiple initializations
38
19
  if (isInitialized || initializingRef.current) {
39
- console.log('SDK already initialized or initializing, skipping...');
40
20
  return;
41
21
  }
42
22
  initializingRef.current = true;
43
23
  try {
44
- console.log('Initializing PERS SDK with config:', config);
45
- // Create React Native auth provider
46
- const auth = new ReactNativeSDKAuthProvider(config.apiProjectKey || 'default-project');
47
- setAuthProvider(auth);
48
24
  // Create HTTP client
49
25
  const httpClient = new ReactNativeHttpClient();
50
- // Create config with auth provider - use the ReactNative auth provider directly
26
+ // Create platform-aware auth provider if not provided
27
+ let authProvider;
28
+ if (config.authProvider) {
29
+ authProvider = config.authProvider;
30
+ }
31
+ else {
32
+ // Use our platform-aware auth provider that automatically selects LocalStorage (web) or AsyncStorage (mobile)
33
+ authProvider = createReactNativeAuthProvider(config.apiProjectKey || 'default-project', {
34
+ debug: false
35
+ });
36
+ }
37
+ // Enhanced config with platform-appropriate auth provider
51
38
  const sdkConfig = {
52
39
  ...config,
53
- authProvider: auth
40
+ authProvider
54
41
  };
55
- // Initialize PersSDK with manager pattern
42
+ // Initialize PersSDK with platform-aware auth provider
56
43
  const sdkInstance = new PersSDK(httpClient, sdkConfig);
44
+ setAuthProvider(authProvider);
57
45
  setSdk(sdkInstance);
58
46
  setIsInitialized(true);
59
- console.log('PERS SDK initialized successfully');
60
47
  }
61
48
  catch (error) {
62
49
  console.error('Failed to initialize PERS SDK:', error);
@@ -77,10 +64,8 @@ export const PersSDKProvider = ({ children }) => {
77
64
  throw new Error('SDK not initialized or not authenticated. Cannot refresh user data.');
78
65
  }
79
66
  try {
80
- console.log('Refreshing user data from remote server...');
81
67
  const freshUserData = await sdk.users.getCurrentUser();
82
68
  setUser(freshUserData);
83
- console.log('User data refreshed successfully:', freshUserData);
84
69
  }
85
70
  catch (error) {
86
71
  console.error('Failed to refresh user data:', error);
@@ -1,47 +1,36 @@
1
- import type { PersAuthProvider } from '@explorins/pers-sdk/core';
2
1
  /**
3
- * Configuration options for React Native Auth Provider
2
+ * React Native Unified Auth Provider
3
+ *
4
+ * Creates a platform-specific auth provider that automatically selects the appropriate storage:
5
+ * - Web: Uses LocalStorageTokenStorage from core SDK
6
+ * - Mobile: Uses AsyncStorage-based storage
7
+ */
8
+ import { DefaultAuthProvider, AuthType } from '@explorins/pers-sdk/core';
9
+ import type { TokenStorage } from '@explorins/pers-sdk/core';
10
+ /**
11
+ * Configuration for React Native Auth Provider
4
12
  */
5
13
  export interface ReactNativeAuthConfig {
6
- /** Use secure storage (Keychain) for tokens when available */
7
- useSecureStorage?: boolean;
8
- /** Custom key prefix for storage */
14
+ /** Custom storage key prefix */
9
15
  keyPrefix?: string;
10
16
  /** Enable debug logging */
11
17
  debug?: boolean;
18
+ /** Custom token storage implementation */
19
+ customStorage?: TokenStorage;
20
+ /** Authentication type (default: 'user') */
21
+ authType?: AuthType;
12
22
  }
13
23
  /**
14
- * React Native Authentication Provider
24
+ * Create a React Native auth provider with platform-appropriate storage
15
25
  *
16
- * Simple, unified implementation for React Native apps with:
17
- * - AsyncStorage for basic token storage
18
- * - Keychain integration for secure storage (when available)
19
- * - Automatic fallback to AsyncStorage if Keychain is unavailable
20
- * - Cross-platform compatibility (iOS/Android/Expo)
26
+ * Automatically selects storage implementation:
27
+ * - Web: Uses LocalStorageTokenStorage (from core SDK)
28
+ * - Mobile: Uses AsyncStorageTokenStorage (React Native specific)
29
+ *
30
+ * @param projectKey - PERS project key
31
+ * @param authApi - Optional auth API instance
32
+ * @param config - Configuration options
33
+ * @returns DefaultAuthProvider configured for the current platform
21
34
  */
22
- export declare class ReactNativeAuthProvider implements PersAuthProvider {
23
- readonly authType: 'user';
24
- private readonly config;
25
- private readonly ACCESS_TOKEN_KEY;
26
- private readonly REFRESH_TOKEN_KEY;
27
- private readonly projectKey;
28
- private memoryStorage;
29
- constructor(projectKey: string, config?: ReactNativeAuthConfig);
30
- getProjectKey(): Promise<string | null>;
31
- getToken(): Promise<string | null>;
32
- setAccessToken(token: string): Promise<void>;
33
- setRefreshToken(token: string): Promise<void>;
34
- getRefreshToken(): Promise<string | null>;
35
- clearTokens(): Promise<void>;
36
- onTokenExpired(): Promise<void>;
37
- hasValidToken(): boolean;
38
- hasRefreshToken(): boolean;
39
- private storeValue;
40
- private getStoredValue;
41
- private removeStoredValue;
42
- private isKeychainAvailable;
43
- private storeInKeychain;
44
- private getFromKeychain;
45
- private removeFromKeychain;
46
- }
35
+ export declare function createReactNativeAuthProvider(projectKey: string, config?: ReactNativeAuthConfig): DefaultAuthProvider;
47
36
  //# sourceMappingURL=react-native-auth-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"react-native-auth-provider.d.ts","sourceRoot":"","sources":["../../src/providers/react-native-auth-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAGjE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,qBAAa,uBAAwB,YAAW,gBAAgB;IAC9D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAU;IAEnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAGpC,OAAO,CAAC,aAAa,CAAkC;gBAGrD,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,qBAA0B;IA4B9B,aAAa,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIvC,QAAQ,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIlC,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7C,eAAe,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAIzC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IASrC,aAAa,IAAI,OAAO;IAIxB,eAAe,IAAI,OAAO;YAKZ,UAAU;YAcV,cAAc;YAcd,iBAAiB;YAgBjB,mBAAmB;YASnB,eAAe;YAKf,eAAe;YAMf,kBAAkB;CAIjC"}
1
+ {"version":3,"file":"react-native-auth-provider.d.ts","sourceRoot":"","sources":["../../src/providers/react-native-auth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAW,QAAQ,EAA4B,MAAM,0BAA0B,CAAC;AAE5G,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAK7D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,qBAA0B,GACjC,mBAAmB,CAyBrB"}
@@ -1,150 +1,40 @@
1
- import AsyncStorage from '@react-native-async-storage/async-storage';
2
1
  /**
3
- * React Native Authentication Provider
2
+ * React Native Unified Auth Provider
4
3
  *
5
- * Simple, unified implementation for React Native apps with:
6
- * - AsyncStorage for basic token storage
7
- * - Keychain integration for secure storage (when available)
8
- * - Automatic fallback to AsyncStorage if Keychain is unavailable
9
- * - Cross-platform compatibility (iOS/Android/Expo)
4
+ * Creates a platform-specific auth provider that automatically selects the appropriate storage:
5
+ * - Web: Uses LocalStorageTokenStorage from core SDK
6
+ * - Mobile: Uses AsyncStorage-based storage
10
7
  */
11
- export class ReactNativeAuthProvider {
12
- constructor(projectKey, config = {}) {
13
- this.authType = 'user';
14
- // In-memory fallback storage
15
- this.memoryStorage = new Map();
16
- if (!projectKey || typeof projectKey !== 'string') {
17
- throw new Error('ReactNativeAuthProvider: projectKey is required and must be a string');
18
- }
19
- this.projectKey = projectKey;
20
- // Set default configuration
21
- this.config = {
22
- useSecureStorage: true, // Default to secure storage when available
23
- keyPrefix: `pers_${projectKey.slice(0, 8)}`,
24
- debug: false,
25
- ...config
26
- };
27
- // Create storage keys
28
- this.ACCESS_TOKEN_KEY = `${this.config.keyPrefix}_access_token`;
29
- this.REFRESH_TOKEN_KEY = `${this.config.keyPrefix}_refresh_token`;
30
- if (this.config.debug) {
31
- console.log('ReactNativeAuthProvider initialized:', {
32
- projectKey: projectKey.slice(0, 8) + '...',
33
- useSecureStorage: this.config.useSecureStorage
34
- });
35
- }
36
- }
37
- async getProjectKey() {
38
- return this.projectKey;
39
- }
40
- async getToken() {
41
- return this.getStoredValue(this.ACCESS_TOKEN_KEY);
42
- }
43
- async setAccessToken(token) {
44
- await this.storeValue(this.ACCESS_TOKEN_KEY, token);
45
- if (this.config.debug) {
46
- console.log('Access token stored securely');
47
- }
48
- }
49
- async setRefreshToken(token) {
50
- await this.storeValue(this.REFRESH_TOKEN_KEY, token);
51
- if (this.config.debug) {
52
- console.log('Refresh token stored securely');
53
- }
54
- }
55
- async getRefreshToken() {
56
- return this.getStoredValue(this.REFRESH_TOKEN_KEY);
57
- }
58
- async clearTokens() {
59
- await Promise.all([
60
- this.removeStoredValue(this.ACCESS_TOKEN_KEY),
61
- this.removeStoredValue(this.REFRESH_TOKEN_KEY)
62
- ]);
63
- if (this.config.debug) {
64
- console.log('All tokens cleared from storage');
65
- }
66
- }
67
- async onTokenExpired() {
68
- if (this.config.debug) {
69
- console.warn('ReactNativeAuthProvider: Token expired - implement refresh logic in your app');
70
- }
71
- // Clear expired tokens
72
- await this.clearTokens();
73
- }
74
- // Token validation methods
75
- hasValidToken() {
76
- return true; // Actual validation happens in getToken()
77
- }
78
- hasRefreshToken() {
79
- return true; // Actual validation happens in getRefreshToken()
80
- }
81
- // Storage implementation methods
82
- async storeValue(key, value) {
83
- try {
84
- if (this.config.useSecureStorage && await this.isKeychainAvailable()) {
85
- await this.storeInKeychain(key, value);
86
- }
87
- else {
88
- await AsyncStorage.setItem(key, value);
89
- }
90
- }
91
- catch (error) {
92
- console.error(`Failed to store value for key ${key}:`, error);
93
- // Fallback to memory storage
94
- this.memoryStorage.set(key, value);
95
- }
96
- }
97
- async getStoredValue(key) {
98
- try {
99
- if (this.config.useSecureStorage && await this.isKeychainAvailable()) {
100
- return await this.getFromKeychain(key);
101
- }
102
- else {
103
- return await AsyncStorage.getItem(key);
104
- }
105
- }
106
- catch (error) {
107
- console.warn(`Failed to get value for key ${key}:`, error);
108
- // Fallback to memory storage
109
- return this.memoryStorage.get(key) || null;
110
- }
111
- }
112
- async removeStoredValue(key) {
113
- try {
114
- if (this.config.useSecureStorage && await this.isKeychainAvailable()) {
115
- await this.removeFromKeychain(key);
116
- }
117
- else {
118
- await AsyncStorage.removeItem(key);
119
- }
120
- }
121
- catch (error) {
122
- console.error(`Failed to remove value for key ${key}:`, error);
123
- }
124
- // Ensure memory fallback is also cleared
125
- this.memoryStorage.delete(key);
126
- }
127
- // Keychain helper methods
128
- async isKeychainAvailable() {
129
- try {
130
- const Keychain = require('react-native-keychain');
131
- return !!Keychain && typeof Keychain.setInternetCredentials === 'function';
132
- }
133
- catch {
134
- return false;
135
- }
136
- }
137
- async storeInKeychain(key, value) {
138
- const Keychain = require('react-native-keychain');
139
- await Keychain.setInternetCredentials(key, 'pers-token', value);
140
- }
141
- async getFromKeychain(key) {
142
- const Keychain = require('react-native-keychain');
143
- const credentials = await Keychain.getInternetCredentials(key);
144
- return credentials ? credentials.password : null;
145
- }
146
- async removeFromKeychain(key) {
147
- const Keychain = require('react-native-keychain');
148
- await Keychain.resetInternetCredentials(key);
149
- }
8
+ import { Platform } from 'react-native';
9
+ import { DefaultAuthProvider, LocalStorageTokenStorage } from '@explorins/pers-sdk/core';
10
+ import { AsyncStorageTokenStorage } from '../storage/async-storage-token-storage';
11
+ // Use React Native's built-in platform detection
12
+ const isWebPlatform = Platform.OS === 'web';
13
+ /**
14
+ * Create a React Native auth provider with platform-appropriate storage
15
+ *
16
+ * Automatically selects storage implementation:
17
+ * - Web: Uses LocalStorageTokenStorage (from core SDK)
18
+ * - Mobile: Uses AsyncStorageTokenStorage (React Native specific)
19
+ *
20
+ * @param projectKey - PERS project key
21
+ * @param authApi - Optional auth API instance
22
+ * @param config - Configuration options
23
+ * @returns DefaultAuthProvider configured for the current platform
24
+ */
25
+ export function createReactNativeAuthProvider(projectKey, config = {}) {
26
+ if (!projectKey || typeof projectKey !== 'string') {
27
+ throw new Error('createReactNativeAuthProvider: projectKey is required and must be a string');
28
+ }
29
+ const { keyPrefix = `pers_${projectKey.slice(0, 8)}_`, debug = false, customStorage, authType = 'user' } = config;
30
+ // Platform-specific storage selection
31
+ const tokenStorage = customStorage || (isWebPlatform
32
+ ? new LocalStorageTokenStorage()
33
+ : new AsyncStorageTokenStorage(keyPrefix));
34
+ // Return DefaultAuthProvider configured with platform-appropriate storage
35
+ return new DefaultAuthProvider({
36
+ authType,
37
+ projectKey,
38
+ storage: tokenStorage
39
+ });
150
40
  }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * AsyncStorage Token Storage for React Native Mobile Platforms
3
+ *
4
+ * Bundler-agnostic AsyncStorage implementation for mobile platforms
5
+ */
6
+ import type { TokenStorage } from '@explorins/pers-sdk/core';
7
+ /**
8
+ * AsyncStorage implementation for mobile platforms
9
+ *
10
+ * This class is only used on mobile platforms (iOS/Android).
11
+ * Web platforms use LocalStorageTokenStorage from core SDK.
12
+ */
13
+ export declare class AsyncStorageTokenStorage implements TokenStorage {
14
+ private keyPrefix;
15
+ private asyncStorage;
16
+ constructor(keyPrefix?: string);
17
+ set(key: string, value: string): Promise<void>;
18
+ get(key: string): Promise<string | null>;
19
+ remove(key: string): Promise<void>;
20
+ clear(): Promise<void>;
21
+ }
22
+ //# sourceMappingURL=async-storage-token-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-storage-token-storage.d.ts","sourceRoot":"","sources":["../../src/storage/async-storage-token-storage.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AA8D7D;;;;;GAKG;AACH,qBAAa,wBAAyB,YAAW,YAAY;IAC3D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA8B;gBAEtC,SAAS,GAAE,MAAuB;IAexC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IASxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAY7B"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * AsyncStorage Token Storage for React Native Mobile Platforms
3
+ *
4
+ * Bundler-agnostic AsyncStorage implementation for mobile platforms
5
+ */
6
+ import AsyncStorage from '@react-native-async-storage/async-storage';
7
+ /**
8
+ * Bundler-agnostic AsyncStorage wrapper
9
+ * Handles different module resolution patterns across bundlers (Metro, Webpack, Rollup, etc.)
10
+ */
11
+ class BundlerAgnosticAsyncStorage {
12
+ constructor(asyncStorageModule) {
13
+ // Try different import patterns to handle various bundlers
14
+ if (asyncStorageModule?.default?.getItem) {
15
+ // Metro/Webpack pattern: { default: { getItem, setItem, ... } }
16
+ this.storage = asyncStorageModule.default;
17
+ }
18
+ else if (asyncStorageModule?.getItem) {
19
+ // Direct export pattern: { getItem, setItem, ... }
20
+ this.storage = asyncStorageModule;
21
+ }
22
+ else if (typeof asyncStorageModule === 'function') {
23
+ // Function export pattern (some bundlers)
24
+ this.storage = asyncStorageModule();
25
+ }
26
+ else {
27
+ // Log the structure for debugging
28
+ console.error('[BundlerAgnosticAsyncStorage] Unknown AsyncStorage structure:', asyncStorageModule);
29
+ throw new Error('AsyncStorage methods not found. Expected structure with getItem/setItem methods. ' +
30
+ 'Make sure @react-native-async-storage/async-storage is properly installed.');
31
+ }
32
+ // Validate that we have the required methods
33
+ const requiredMethods = ['getItem', 'setItem', 'removeItem', 'getAllKeys', 'multiRemove'];
34
+ const missingMethods = requiredMethods.filter(method => typeof this.storage[method] !== 'function');
35
+ if (missingMethods.length > 0) {
36
+ throw new Error(`AsyncStorage missing required methods: ${missingMethods.join(', ')}. ` +
37
+ 'Ensure @react-native-async-storage/async-storage is properly installed and compatible.');
38
+ }
39
+ }
40
+ async getItem(key) {
41
+ return this.storage.getItem(key);
42
+ }
43
+ async setItem(key, value) {
44
+ return this.storage.setItem(key, value);
45
+ }
46
+ async removeItem(key) {
47
+ return this.storage.removeItem(key);
48
+ }
49
+ async getAllKeys() {
50
+ return this.storage.getAllKeys();
51
+ }
52
+ async multiRemove(keys) {
53
+ return this.storage.multiRemove(keys);
54
+ }
55
+ }
56
+ /**
57
+ * AsyncStorage implementation for mobile platforms
58
+ *
59
+ * This class is only used on mobile platforms (iOS/Android).
60
+ * Web platforms use LocalStorageTokenStorage from core SDK.
61
+ */
62
+ export class AsyncStorageTokenStorage {
63
+ constructor(keyPrefix = 'pers_tokens_') {
64
+ this.keyPrefix = keyPrefix;
65
+ try {
66
+ // Initialize bundler-agnostic AsyncStorage wrapper
67
+ this.asyncStorage = new BundlerAgnosticAsyncStorage(AsyncStorage);
68
+ }
69
+ catch (error) {
70
+ console.error('[AsyncStorageTokenStorage] Failed to initialize:', error);
71
+ throw new Error('Failed to initialize AsyncStorage. Make sure @react-native-async-storage/async-storage is installed and ' +
72
+ 'this code is running on a React Native mobile platform (not web).');
73
+ }
74
+ }
75
+ async set(key, value) {
76
+ try {
77
+ await this.asyncStorage.setItem(`${this.keyPrefix}${key}`, value);
78
+ }
79
+ catch (error) {
80
+ console.error(`Failed to store token ${key}:`, error);
81
+ throw new Error(`Token storage failed: ${error}`);
82
+ }
83
+ }
84
+ async get(key) {
85
+ try {
86
+ return await this.asyncStorage.getItem(`${this.keyPrefix}${key}`);
87
+ }
88
+ catch (error) {
89
+ console.error(`Failed to retrieve token ${key}:`, error);
90
+ return null;
91
+ }
92
+ }
93
+ async remove(key) {
94
+ try {
95
+ await this.asyncStorage.removeItem(`${this.keyPrefix}${key}`);
96
+ }
97
+ catch (error) {
98
+ console.error(`Failed to remove token ${key}:`, error);
99
+ }
100
+ }
101
+ async clear() {
102
+ try {
103
+ const allKeys = await this.asyncStorage.getAllKeys();
104
+ const ourKeys = allKeys.filter(key => key.startsWith(this.keyPrefix));
105
+ if (ourKeys.length > 0) {
106
+ await this.asyncStorage.multiRemove(ourKeys);
107
+ }
108
+ }
109
+ catch (error) {
110
+ console.error('Failed to clear token storage:', error);
111
+ }
112
+ }
113
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@explorins/pers-sdk-react-native",
3
- "version": "1.5.18",
4
- "description": "React Native SDK for PERS Platform - Tourism Loyalty System with Manager Pattern Architecture",
3
+ "version": "1.5.20",
4
+ "description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
@@ -26,24 +26,27 @@
26
26
  "tourism",
27
27
  "loyalty",
28
28
  "blockchain",
29
- "web3"
29
+ "web3",
30
+ "webauthn",
31
+ "transaction-signing",
32
+ "rewards",
33
+ "authentication",
34
+ "biometrics",
35
+ "secure-storage"
30
36
  ],
31
37
  "author": "eXplorins",
32
38
  "license": "MIT",
33
39
  "dependencies": {
34
40
  "@dfns/sdk": "^0.8.1",
35
41
  "@dfns/sdk-react-native": "^0.8.1",
36
- "@explorins/pers-sdk": "^1.6.3",
37
- "@explorins/pers-shared": "^2.1.40",
38
- "@explorins/pers-signer": "^1.0.12",
42
+ "@explorins/pers-sdk": "^1.6.24",
43
+ "@explorins/pers-shared": "^2.1.44",
44
+ "@explorins/pers-signer": "^1.0.18",
39
45
  "@explorins/web3-ts": "^0.3.75",
40
- "@react-native-async-storage/async-storage": "^2.2.0",
41
46
  "buffer": "^6.0.3",
42
47
  "ethers": "^6.15.0",
43
48
  "react-native-get-random-values": "^2.0.0",
44
- "react-native-keychain": "^10.0.0",
45
- "typedoc": "^0.25.13",
46
- "typedoc-plugin-markdown": "^3.17.1"
49
+ "react-native-keychain": "^10.0.0"
47
50
  },
48
51
  "browser": {
49
52
  "crypto": false,
@@ -93,6 +96,7 @@
93
96
  "@ethersproject/scrypt": false
94
97
  },
95
98
  "peerDependencies": {
99
+ "@react-native-async-storage/async-storage": ">=1.15.0",
96
100
  "react": ">=16.8.0",
97
101
  "react-native": ">=0.60.0"
98
102
  },
@@ -153,7 +157,6 @@
153
157
  "@ethersproject/scrypt": false
154
158
  },
155
159
  "devDependencies": {
156
- "@react-native-async-storage/async-storage": "^1.19.0",
157
160
  "@rollup/plugin-commonjs": "^25.0.7",
158
161
  "@rollup/plugin-json": "^6.1.0",
159
162
  "@rollup/plugin-node-resolve": "^15.2.3",
@@ -162,6 +165,8 @@
162
165
  "rimraf": "^5.0.0",
163
166
  "rollup": "^4.0.0",
164
167
  "rollup-plugin-typescript2": "^0.36.0",
168
+ "typedoc": "^0.25.13",
169
+ "typedoc-plugin-markdown": "^3.17.1",
165
170
  "typescript": "^5.2.0"
166
171
  },
167
172
  "files": [
@@ -17,4 +17,4 @@ export { useDonations } from './useDonations';
17
17
 
18
18
  // Re-export auth-related types for convenience
19
19
  export type { RawUserData } from './useAuth';
20
- export type { TransactionSignerHook, TransactionSigningResult } from './useTransactionSigner';
20
+ export type { TransactionSignerHook, SubmissionResult, AuthenticatedUser, TransactionSigningResult } from './useTransactionSigner';
@@ -79,7 +79,7 @@ export const useAuth = () => {
79
79
  console.log(`Logging in as ${userType}...`);
80
80
 
81
81
  // Set token in auth provider
82
- await authProvider.setToken(jwtToken);
82
+ await authProvider.setAccessToken(jwtToken);
83
83
 
84
84
  // Perform login using the manager
85
85
  const result = await sdk.auth.loginWithToken(jwtToken, userType);
@@ -124,12 +124,12 @@ export const useAuth = () => {
124
124
  try {
125
125
  console.log('Logging in with raw user data...');
126
126
 
127
- // Use the raw data login from the API client directly
128
- const result = await sdk.api().loginUserWithRawData(rawUserData);
127
+ // Use the raw data login from the auth manager
128
+ const result = await sdk.auth.loginWithRawData(rawUserData);
129
129
 
130
130
  // Set token from result
131
131
  if (result.accessToken) {
132
- await authProvider.setToken(result.accessToken);
132
+ await authProvider.setAccessToken(result.accessToken);
133
133
  }
134
134
 
135
135
  const userData = result.user;
@@ -168,7 +168,7 @@ export const useAuth = () => {
168
168
  console.log('Logging out...');
169
169
 
170
170
  if (authProvider) {
171
- await authProvider.setToken(null);
171
+ await authProvider.clearTokens();
172
172
  }
173
173
 
174
174
  setAuthenticationState(null, null, false);
@@ -272,11 +272,11 @@ export const useAuth = () => {
272
272
  * console.log('Auth is valid:', isValid);
273
273
  * ```
274
274
  */
275
- const hasValidAuth = useCallback((): boolean => {
275
+ const hasValidAuth = useCallback(async (): Promise<boolean> => {
276
276
  if (!sdk) {
277
277
  return false;
278
278
  }
279
- return sdk.auth.hasValidAuth();
279
+ return await sdk.auth.hasValidAuth();
280
280
  }, [sdk]);
281
281
 
282
282
  return {