@explorins/pers-sdk-react-native 1.3.2

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 (63) hide show
  1. package/README.md +200 -0
  2. package/dist/hooks/index.d.ts +8 -0
  3. package/dist/hooks/index.d.ts.map +1 -0
  4. package/dist/hooks/index.js +8 -0
  5. package/dist/hooks/useAuth.d.ts +12 -0
  6. package/dist/hooks/useAuth.d.ts.map +1 -0
  7. package/dist/hooks/useAuth.js +16 -0
  8. package/dist/hooks/useBusiness.d.ts +7 -0
  9. package/dist/hooks/useBusiness.d.ts.map +1 -0
  10. package/dist/hooks/useBusiness.js +64 -0
  11. package/dist/hooks/useCampaigns.d.ts +8 -0
  12. package/dist/hooks/useCampaigns.d.ts.map +1 -0
  13. package/dist/hooks/useCampaigns.js +90 -0
  14. package/dist/hooks/useRedemptions.d.ts +9 -0
  15. package/dist/hooks/useRedemptions.d.ts.map +1 -0
  16. package/dist/hooks/useRedemptions.js +121 -0
  17. package/dist/hooks/useTokens.d.ts +6 -0
  18. package/dist/hooks/useTokens.d.ts.map +1 -0
  19. package/dist/hooks/useTokens.js +48 -0
  20. package/dist/hooks/useTransactions.d.ts +7 -0
  21. package/dist/hooks/useTransactions.d.ts.map +1 -0
  22. package/dist/hooks/useTransactions.js +78 -0
  23. package/dist/hooks/useWeb3.d.ts +11 -0
  24. package/dist/hooks/useWeb3.d.ts.map +1 -0
  25. package/dist/hooks/useWeb3.js +63 -0
  26. package/dist/index.d.ts +7 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.esm.js +1057 -0
  29. package/dist/index.esm.js.map +1 -0
  30. package/dist/index.js +1077 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/polyfills/index.d.ts +3 -0
  33. package/dist/polyfills/index.d.ts.map +1 -0
  34. package/dist/polyfills/index.js +13 -0
  35. package/dist/polyfills/index.simple.d.ts +2 -0
  36. package/dist/polyfills/index.simple.d.ts.map +1 -0
  37. package/dist/polyfills/index.simple.js +17 -0
  38. package/dist/providers/PersSDKProvider.d.ts +29 -0
  39. package/dist/providers/PersSDKProvider.d.ts.map +1 -0
  40. package/dist/providers/PersSDKProvider.js +194 -0
  41. package/dist/providers/react-native-auth-provider.d.ts +92 -0
  42. package/dist/providers/react-native-auth-provider.d.ts.map +1 -0
  43. package/dist/providers/react-native-auth-provider.js +268 -0
  44. package/dist/providers/react-native-http-client.d.ts +29 -0
  45. package/dist/providers/react-native-http-client.d.ts.map +1 -0
  46. package/dist/providers/react-native-http-client.js +94 -0
  47. package/package.json +157 -0
  48. package/src/hooks/index.ts +8 -0
  49. package/src/hooks/useAuth.ts +43 -0
  50. package/src/hooks/useBusiness.ts +69 -0
  51. package/src/hooks/useCampaigns.ts +96 -0
  52. package/src/hooks/useRedemptions.ts +129 -0
  53. package/src/hooks/useTokens.ts +53 -0
  54. package/src/hooks/useTransactions.ts +85 -0
  55. package/src/hooks/useWeb3.ts +70 -0
  56. package/src/index.ts +51 -0
  57. package/src/polyfills/index.simple.ts +22 -0
  58. package/src/polyfills/index.ts +16 -0
  59. package/src/providers/PersSDKProvider.tsx +274 -0
  60. package/src/providers/react-native-auth-provider.ts +332 -0
  61. package/src/providers/react-native-http-client.ts +129 -0
  62. package/src/types/external-modules.d.ts +13 -0
  63. package/src/types/react-native-globals.d.ts +46 -0
package/dist/index.js ADDED
@@ -0,0 +1,1077 @@
1
+
2
+ // React Native optimized CJS bundle
3
+ // Node.js dependencies excluded for web compatibility
4
+
5
+ 'use strict';
6
+
7
+ var AsyncStorage = require('@react-native-async-storage/async-storage');
8
+ var jsxRuntime = require('react/jsx-runtime');
9
+ var react = require('react');
10
+ var core = require('@explorins/pers-sdk/core');
11
+ var token = require('@explorins/pers-sdk/token');
12
+ var transaction = require('@explorins/pers-sdk/transaction');
13
+ var business = require('@explorins/pers-sdk/business');
14
+ var campaign = require('@explorins/pers-sdk/campaign');
15
+ var redemption = require('@explorins/pers-sdk/redemption');
16
+ var web3 = require('@explorins/pers-sdk/web3');
17
+
18
+ // Minimal React Native environment setup
19
+ // No polyfills needed - modules are disabled at Metro level
20
+ // Simple initialization function for compatibility
21
+ const initializeReactNativePolyfills = () => {
22
+ console.log('✅ [PERS SDK] React Native environment ready (no polyfills needed)');
23
+ return true;
24
+ };
25
+ // Platform detection
26
+ const isReactNative = () => {
27
+ return typeof navigator !== 'undefined' && navigator.product === 'ReactNative';
28
+ };
29
+ // Auto-initialize
30
+ initializeReactNativePolyfills();
31
+
32
+ /**
33
+ * Storage strategy for different types of data
34
+ */
35
+ exports.StorageStrategy = void 0;
36
+ (function (StorageStrategy) {
37
+ /** Use AsyncStorage for general app data */
38
+ StorageStrategy["ASYNC_STORAGE"] = "async_storage";
39
+ /** Use Keychain for sensitive tokens (when available) */
40
+ StorageStrategy["KEYCHAIN"] = "keychain";
41
+ /** Use in-memory storage (fallback) */
42
+ StorageStrategy["MEMORY"] = "memory";
43
+ })(exports.StorageStrategy || (exports.StorageStrategy = {}));
44
+ /**
45
+ * Base React Native Authentication Provider
46
+ *
47
+ * This serves as a blueprint for native implementations and can be extended
48
+ * by consuming applications to integrate with their specific auth systems.
49
+ *
50
+ * Features:
51
+ * - Multiple storage strategies (AsyncStorage, Keychain, Memory)
52
+ * - Configurable security levels per token type
53
+ * - Cross-platform compatibility (iOS/Android/Web)
54
+ * - Blueprint for native iOS/Android implementations
55
+ */
56
+ class BaseReactNativeAuthProvider {
57
+ constructor(projectKey, config = {}) {
58
+ // In-memory fallback storage
59
+ this.memoryStorage = new Map();
60
+ // Validate projectKey
61
+ if (!projectKey || typeof projectKey !== 'string') {
62
+ throw new Error('ReactNativeAuthProvider: projectKey is required and must be a string');
63
+ }
64
+ // Set default configuration
65
+ this.config = {
66
+ accessTokenStrategy: exports.StorageStrategy.ASYNC_STORAGE,
67
+ refreshTokenStrategy: exports.StorageStrategy.KEYCHAIN,
68
+ keyPrefix: `pers_${projectKey.slice(0, 8)}`,
69
+ debug: false,
70
+ ...config
71
+ };
72
+ // Create storage keys
73
+ this.ACCESS_TOKEN_KEY = `${this.config.keyPrefix}_access_token`;
74
+ this.REFRESH_TOKEN_KEY = `${this.config.keyPrefix}_refresh_token`;
75
+ this.PROJECT_KEY_KEY = `${this.config.keyPrefix}_project_key`;
76
+ if (this.config.debug) {
77
+ console.log('🔧 ReactNativeAuthProvider initialized with config:', this.config);
78
+ }
79
+ }
80
+ // Core token management methods
81
+ async getToken() {
82
+ return this.getStoredValue(this.ACCESS_TOKEN_KEY, this.config.accessTokenStrategy);
83
+ }
84
+ async setAccessToken(token) {
85
+ await this.storeValue(this.ACCESS_TOKEN_KEY, token, this.config.accessTokenStrategy);
86
+ if (this.config.debug) {
87
+ console.log('✅ Access token stored securely');
88
+ }
89
+ }
90
+ async setRefreshToken(token) {
91
+ await this.storeValue(this.REFRESH_TOKEN_KEY, token, this.config.refreshTokenStrategy);
92
+ if (this.config.debug) {
93
+ console.log('✅ Refresh token stored securely');
94
+ }
95
+ }
96
+ async getRefreshToken() {
97
+ return this.getStoredValue(this.REFRESH_TOKEN_KEY, this.config.refreshTokenStrategy);
98
+ }
99
+ async clearTokens() {
100
+ await Promise.all([
101
+ this.removeStoredValue(this.ACCESS_TOKEN_KEY, this.config.accessTokenStrategy),
102
+ this.removeStoredValue(this.REFRESH_TOKEN_KEY, this.config.refreshTokenStrategy)
103
+ ]);
104
+ if (this.config.debug) {
105
+ console.log('✅ All tokens cleared from storage');
106
+ }
107
+ }
108
+ // Token validation methods
109
+ hasValidToken() {
110
+ // Synchronous check - for async check use hasValidTokenAsync()
111
+ return true; // Actual validation happens in getToken()
112
+ }
113
+ hasRefreshToken() {
114
+ // Synchronous check - for async check use hasRefreshTokenAsync()
115
+ return true; // Actual validation happens in getRefreshToken()
116
+ }
117
+ // Async token validation methods
118
+ async hasValidTokenAsync() {
119
+ const token = await this.getToken();
120
+ return !!token;
121
+ }
122
+ async hasRefreshTokenAsync() {
123
+ const refreshToken = await this.getRefreshToken();
124
+ return !!refreshToken;
125
+ }
126
+ // Legacy methods for backward compatibility
127
+ setToken(token) {
128
+ this.setAccessToken(token).catch(error => {
129
+ console.error('Legacy setToken failed:', error);
130
+ });
131
+ }
132
+ clearToken() {
133
+ this.clearTokens().catch(error => {
134
+ console.error('Legacy clearToken failed:', error);
135
+ });
136
+ }
137
+ // Protected storage implementation methods
138
+ async storeValue(key, value, strategy) {
139
+ try {
140
+ switch (strategy) {
141
+ case exports.StorageStrategy.KEYCHAIN:
142
+ // Try Keychain first, fallback to AsyncStorage
143
+ if (await this.isKeychainAvailable()) {
144
+ await this.storeInKeychain(key, value);
145
+ }
146
+ else {
147
+ await AsyncStorage.setItem(key, value);
148
+ }
149
+ break;
150
+ case exports.StorageStrategy.ASYNC_STORAGE:
151
+ await AsyncStorage.setItem(key, value);
152
+ break;
153
+ case exports.StorageStrategy.MEMORY:
154
+ default:
155
+ this.memoryStorage.set(key, value);
156
+ break;
157
+ }
158
+ }
159
+ catch (error) {
160
+ console.error(`Failed to store value with strategy ${strategy}:`, error);
161
+ // Fallback to memory storage
162
+ this.memoryStorage.set(key, value);
163
+ }
164
+ }
165
+ async getStoredValue(key, strategy) {
166
+ try {
167
+ switch (strategy) {
168
+ case exports.StorageStrategy.KEYCHAIN:
169
+ // Try Keychain first, fallback to AsyncStorage
170
+ if (await this.isKeychainAvailable()) {
171
+ return await this.getFromKeychain(key);
172
+ }
173
+ else {
174
+ return await AsyncStorage.getItem(key);
175
+ }
176
+ case exports.StorageStrategy.ASYNC_STORAGE:
177
+ return await AsyncStorage.getItem(key);
178
+ case exports.StorageStrategy.MEMORY:
179
+ default:
180
+ return this.memoryStorage.get(key) || null;
181
+ }
182
+ }
183
+ catch (error) {
184
+ console.warn(`Failed to get value with strategy ${strategy}:`, error);
185
+ // Fallback to memory storage
186
+ return this.memoryStorage.get(key) || null;
187
+ }
188
+ }
189
+ async removeStoredValue(key, strategy) {
190
+ try {
191
+ switch (strategy) {
192
+ case exports.StorageStrategy.KEYCHAIN:
193
+ // Try Keychain first, fallback to AsyncStorage
194
+ if (await this.isKeychainAvailable()) {
195
+ await this.removeFromKeychain(key);
196
+ }
197
+ else {
198
+ await AsyncStorage.removeItem(key);
199
+ }
200
+ break;
201
+ case exports.StorageStrategy.ASYNC_STORAGE:
202
+ await AsyncStorage.removeItem(key);
203
+ break;
204
+ case exports.StorageStrategy.MEMORY:
205
+ default:
206
+ this.memoryStorage.delete(key);
207
+ break;
208
+ }
209
+ }
210
+ catch (error) {
211
+ console.error(`Failed to remove value with strategy ${strategy}:`, error);
212
+ // Ensure memory fallback is also cleared
213
+ this.memoryStorage.delete(key);
214
+ }
215
+ }
216
+ // Keychain helper methods
217
+ async isKeychainAvailable() {
218
+ try {
219
+ // Check if react-native-keychain is available
220
+ const Keychain = require('react-native-keychain');
221
+ return !!Keychain && typeof Keychain.setInternetCredentials === 'function';
222
+ }
223
+ catch {
224
+ return false;
225
+ }
226
+ }
227
+ async storeInKeychain(key, value) {
228
+ const Keychain = require('react-native-keychain');
229
+ await Keychain.setInternetCredentials(key, 'pers-token', value);
230
+ }
231
+ async getFromKeychain(key) {
232
+ const Keychain = require('react-native-keychain');
233
+ const credentials = await Keychain.getInternetCredentials(key);
234
+ return credentials ? credentials.password : null;
235
+ }
236
+ async removeFromKeychain(key) {
237
+ const Keychain = require('react-native-keychain');
238
+ await Keychain.resetInternetCredentials(key);
239
+ }
240
+ }
241
+ /**
242
+ * React Native Authentication Provider
243
+ *
244
+ * A ready-to-use implementation for basic use cases.
245
+ * Uses AsyncStorage for access tokens and Keychain for refresh tokens (when available).
246
+ */
247
+ class ReactNativeAuthProvider extends BaseReactNativeAuthProvider {
248
+ constructor(projectKey, config = {}) {
249
+ // Validate projectKey
250
+ if (!projectKey || typeof projectKey !== 'string') {
251
+ throw new Error('ReactNativeAuthProvider: projectKey is required and must be a string');
252
+ }
253
+ super(projectKey, {
254
+ accessTokenStrategy: exports.StorageStrategy.ASYNC_STORAGE,
255
+ refreshTokenStrategy: exports.StorageStrategy.KEYCHAIN,
256
+ debug: false,
257
+ ...config
258
+ });
259
+ this.projectKey = projectKey;
260
+ this.authType = 'user';
261
+ }
262
+ async getProjectKey() {
263
+ return this.projectKey;
264
+ }
265
+ async onTokenExpired() {
266
+ if (this.config.debug) {
267
+ console.warn('ReactNativeAuthProvider: Token expired - no refresh logic implemented');
268
+ }
269
+ }
270
+ }
271
+ /**
272
+ * Secure React Native Authentication Provider
273
+ *
274
+ * Maximum security implementation using Keychain for all sensitive data.
275
+ */
276
+ class SecureReactNativeAuthProvider extends BaseReactNativeAuthProvider {
277
+ constructor(projectKey, config = {}) {
278
+ // Validate projectKey
279
+ if (!projectKey || typeof projectKey !== 'string') {
280
+ throw new Error('SecureReactNativeAuthProvider: projectKey is required and must be a string');
281
+ }
282
+ super(projectKey, {
283
+ ...config,
284
+ accessTokenStrategy: exports.StorageStrategy.KEYCHAIN,
285
+ refreshTokenStrategy: exports.StorageStrategy.KEYCHAIN,
286
+ });
287
+ this.projectKey = projectKey;
288
+ this.authType = 'user';
289
+ }
290
+ async getProjectKey() {
291
+ return this.projectKey;
292
+ }
293
+ async onTokenExpired() {
294
+ if (this.config.debug) {
295
+ console.warn('SecureReactNativeAuthProvider: Token expired - implement refresh logic');
296
+ }
297
+ }
298
+ }
299
+
300
+ /**
301
+ * HTTP Client implementation for React Native
302
+ *
303
+ * This implementation properly implements the core SDK's HttpClient interface
304
+ * and uses fetch API which is available in React Native.
305
+ */
306
+ class ReactNativeHttpClient {
307
+ constructor(baseURL) {
308
+ this.baseURL = baseURL;
309
+ }
310
+ async get(url, options) {
311
+ return this.request('GET', url, undefined, options);
312
+ }
313
+ async post(url, body, options) {
314
+ return this.request('POST', url, body, options);
315
+ }
316
+ async put(url, body, options) {
317
+ return this.request('PUT', url, body, options);
318
+ }
319
+ async delete(url, options) {
320
+ return this.request('DELETE', url, undefined, options);
321
+ }
322
+ async request(method, url, body, options) {
323
+ const fullUrl = this.buildUrl(url, options?.params);
324
+ const config = {
325
+ method,
326
+ headers: {
327
+ 'Content-Type': 'application/json',
328
+ ...options?.headers,
329
+ },
330
+ };
331
+ // Add timeout if specified
332
+ if (options?.timeout) {
333
+ const controller = new AbortController();
334
+ config.signal = controller.signal;
335
+ setTimeout(() => controller.abort(), options.timeout);
336
+ }
337
+ // Add body for POST/PUT requests
338
+ if (body && (method === 'POST' || method === 'PUT')) {
339
+ config.body = JSON.stringify(body);
340
+ }
341
+ try {
342
+ const response = await fetch(fullUrl, config);
343
+ if (!response.ok) {
344
+ // Try to get error details from response
345
+ let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
346
+ try {
347
+ const errorBody = await response.text();
348
+ if (errorBody) {
349
+ errorMessage += ` - ${errorBody}`;
350
+ }
351
+ }
352
+ catch (e) {
353
+ // Ignore errors when reading error body
354
+ }
355
+ throw new Error(errorMessage);
356
+ }
357
+ // Handle different response types
358
+ switch (options?.responseType) {
359
+ case 'text':
360
+ return response.text();
361
+ case 'blob':
362
+ return response.blob();
363
+ case 'arraybuffer':
364
+ return response.arrayBuffer();
365
+ case 'json':
366
+ default:
367
+ // Check if response has content
368
+ const contentLength = response.headers.get('content-length');
369
+ if (contentLength === '0' || response.status === 204) {
370
+ return undefined;
371
+ }
372
+ return response.json();
373
+ }
374
+ }
375
+ catch (error) {
376
+ if (error instanceof Error && error.name === 'AbortError') {
377
+ throw new Error(`Request timeout after ${options?.timeout}ms`);
378
+ }
379
+ throw error;
380
+ }
381
+ }
382
+ buildUrl(url, params) {
383
+ const fullUrl = this.baseURL ? `${this.baseURL}${url}` : url;
384
+ if (!params || Object.keys(params).length === 0) {
385
+ return fullUrl;
386
+ }
387
+ const urlObj = new URL(fullUrl);
388
+ Object.entries(params).forEach(([key, value]) => {
389
+ urlObj.searchParams.append(key, value);
390
+ });
391
+ return urlObj.toString();
392
+ }
393
+ }
394
+
395
+ // Create the context
396
+ const SDKContext = react.createContext(null);
397
+ // Custom auth provider for React Native
398
+ class ReactNativeSDKAuthProvider extends BaseReactNativeAuthProvider {
399
+ constructor(projectKey) {
400
+ super(projectKey);
401
+ this.projectKey = projectKey;
402
+ this.authType = 'user';
403
+ this._token = null;
404
+ }
405
+ async getToken() {
406
+ return this._token;
407
+ }
408
+ async setToken(token) {
409
+ this._token = token;
410
+ }
411
+ async getProjectKey() {
412
+ return this.projectKey;
413
+ }
414
+ async onTokenExpired() {
415
+ console.log('Token expired - clearing token');
416
+ this._token = null;
417
+ }
418
+ }
419
+ // Provider component
420
+ const PersSDKProvider = ({ children }) => {
421
+ const initializingRef = react.useRef(false);
422
+ const [apiClient, setApiClient] = react.useState(null);
423
+ const [authProvider, setAuthProvider] = react.useState(null);
424
+ const [sdks, setSdks] = react.useState({
425
+ tokens: null,
426
+ transactions: null,
427
+ business: null,
428
+ campaigns: null,
429
+ redemptions: null,
430
+ web3: null,
431
+ });
432
+ const [isInitialized, setIsInitialized] = react.useState(false);
433
+ const [isAuthenticated, setIsAuthenticated] = react.useState(false);
434
+ const [user, setUser] = react.useState(null);
435
+ const [accountAddress, setAccountAddress] = react.useState(null);
436
+ const initialize = react.useCallback(async (config) => {
437
+ // Prevent multiple initializations
438
+ if (isInitialized || initializingRef.current) {
439
+ console.log('⚠️ SDK already initialized or initializing, skipping...');
440
+ return;
441
+ }
442
+ initializingRef.current = true;
443
+ try {
444
+ console.log('🚀 Initializing PERS SDK with config:', config);
445
+ // Create auth provider
446
+ const auth = new ReactNativeSDKAuthProvider(config.apiProjectKey);
447
+ setAuthProvider(auth);
448
+ // Create HTTP client
449
+ const httpClient = new ReactNativeHttpClient();
450
+ // Create API client
451
+ const client = new core.PersApiClient(httpClient, {
452
+ apiProjectKey: config.apiProjectKey,
453
+ authProvider: auth,
454
+ environment: config.environment || 'development',
455
+ });
456
+ setApiClient(client);
457
+ // Initialize domain SDKs
458
+ const domainSDKs = {
459
+ tokens: new token.TokenSDK(client),
460
+ transactions: transaction.createTransactionSDK(client),
461
+ business: business.createBusinessSDK(client),
462
+ campaigns: campaign.createCampaignSDK(client),
463
+ redemptions: redemption.createRedemptionSDK(client),
464
+ web3: web3.createWeb3SDK(client),
465
+ };
466
+ setSdks(domainSDKs);
467
+ setIsInitialized(true);
468
+ console.log('✅ PERS SDK initialized successfully');
469
+ }
470
+ catch (error) {
471
+ console.error('❌ Failed to initialize PERS SDK:', error);
472
+ initializingRef.current = false;
473
+ throw error;
474
+ }
475
+ finally {
476
+ initializingRef.current = false;
477
+ }
478
+ }, []);
479
+ const login = react.useCallback(async (jwtToken, userType = 'user') => {
480
+ if (!apiClient || !authProvider) {
481
+ throw new Error('SDK not initialized. Call initialize() first.');
482
+ }
483
+ try {
484
+ console.log(`🔐 Logging in as ${userType}...`);
485
+ // Set token in auth provider
486
+ await authProvider.setToken(jwtToken);
487
+ // Perform login with API client
488
+ const result = userType === 'admin'
489
+ ? await apiClient.loginAdmin(jwtToken)
490
+ : await apiClient.loginUser(jwtToken);
491
+ const userData = result.user || result.admin;
492
+ const userAccountAddress = userData?.accountAddress ||
493
+ userData?.wallets?.[0]?.address ||
494
+ null;
495
+ setUser(userData);
496
+ setAccountAddress(userAccountAddress);
497
+ setIsAuthenticated(true);
498
+ console.log('✅ Login successful');
499
+ return result;
500
+ }
501
+ catch (error) {
502
+ console.error('❌ Login failed:', error);
503
+ throw error;
504
+ }
505
+ }, [apiClient, authProvider]);
506
+ const loginWithRawData = react.useCallback(async (rawUserData) => {
507
+ if (!apiClient || !authProvider) {
508
+ throw new Error('SDK not initialized. Call initialize() first.');
509
+ }
510
+ try {
511
+ console.log('🔐 Logging in with raw user data...');
512
+ const result = await apiClient.loginUserWithRawData(rawUserData);
513
+ // Set token from result
514
+ if (result.accessToken) {
515
+ await authProvider.setToken(result.accessToken);
516
+ }
517
+ const userData = result.user;
518
+ const userAccountAddress = userData?.accountAddress ||
519
+ userData?.wallets?.[0]?.address ||
520
+ null;
521
+ setUser(userData);
522
+ setAccountAddress(userAccountAddress);
523
+ setIsAuthenticated(true);
524
+ console.log('✅ Raw data login successful');
525
+ return result;
526
+ }
527
+ catch (error) {
528
+ console.error('❌ Raw data login failed:', error);
529
+ throw error;
530
+ }
531
+ }, [apiClient, authProvider]);
532
+ const logout = react.useCallback(async () => {
533
+ try {
534
+ console.log('🔓 Logging out...');
535
+ if (authProvider) {
536
+ await authProvider.setToken(null);
537
+ }
538
+ setUser(null);
539
+ setAccountAddress(null);
540
+ setIsAuthenticated(false);
541
+ console.log('✅ Logout successful');
542
+ }
543
+ catch (error) {
544
+ console.error('❌ Logout failed:', error);
545
+ throw error;
546
+ }
547
+ }, [authProvider]);
548
+ const contextValue = {
549
+ // SDK instances
550
+ tokens: sdks.tokens,
551
+ transactions: sdks.transactions,
552
+ business: sdks.business,
553
+ campaigns: sdks.campaigns,
554
+ redemptions: sdks.redemptions,
555
+ web3: sdks.web3,
556
+ apiClient,
557
+ // State
558
+ isInitialized,
559
+ isAuthenticated,
560
+ user,
561
+ accountAddress,
562
+ // Methods
563
+ initialize,
564
+ login,
565
+ loginWithRawData,
566
+ logout,
567
+ };
568
+ return (jsxRuntime.jsx(SDKContext.Provider, { value: contextValue, children: children }));
569
+ };
570
+ // Custom hook to use the SDK context
571
+ const usePersSDK = () => {
572
+ const context = react.useContext(SDKContext);
573
+ if (!context) {
574
+ throw new Error('usePersSDK must be used within a PersSDKProvider');
575
+ }
576
+ return context;
577
+ };
578
+
579
+ const useAuth = () => {
580
+ const { isInitialized, isAuthenticated, user, accountAddress, initialize, login, loginWithRawData, logout, } = usePersSDK();
581
+ return {
582
+ // State
583
+ isInitialized,
584
+ isAuthenticated,
585
+ user,
586
+ accountAddress,
587
+ // Actions
588
+ initialize,
589
+ login,
590
+ loginWithRawData,
591
+ logout,
592
+ };
593
+ };
594
+
595
+ const useTokens = () => {
596
+ const { tokens, isInitialized, isAuthenticated } = usePersSDK();
597
+ if (!isAuthenticated && isInitialized) {
598
+ console.warn('SDK not authenticated. Some token operations may fail.');
599
+ }
600
+ const getTokens = react.useCallback(async () => {
601
+ if (!isInitialized) {
602
+ throw new Error('SDK not initialized. Call initialize() first.');
603
+ }
604
+ if (!tokens?.getTokens) {
605
+ console.warn('getTokens method not available');
606
+ return [];
607
+ }
608
+ try {
609
+ const result = await tokens.getTokens();
610
+ console.log('✅ Tokens fetched successfully:', result);
611
+ return result;
612
+ }
613
+ catch (error) {
614
+ console.error('❌ Failed to fetch tokens:', error);
615
+ throw error;
616
+ }
617
+ }, [tokens]);
618
+ const getTokenById = react.useCallback(async (tokenId) => {
619
+ if (!isInitialized) {
620
+ throw new Error('SDK not initialized. Call initialize() first.');
621
+ }
622
+ if (!tokens?.getTokenById) {
623
+ throw new Error('getTokenById method not available');
624
+ }
625
+ try {
626
+ const result = await tokens.getTokenById(tokenId);
627
+ console.log('✅ Token fetched successfully:', result);
628
+ return result;
629
+ }
630
+ catch (error) {
631
+ console.error('❌ Failed to fetch token:', error);
632
+ throw error;
633
+ }
634
+ }, [tokens]);
635
+ return {
636
+ getTokens,
637
+ getTokenById,
638
+ isAvailable: isInitialized && !!tokens,
639
+ };
640
+ };
641
+
642
+ const useTransactions = () => {
643
+ const { transactions, isInitialized, isAuthenticated } = usePersSDK();
644
+ if (!isAuthenticated && isInitialized) {
645
+ console.warn('SDK not authenticated. Some transaction operations may fail.');
646
+ }
647
+ const createTransaction = react.useCallback(async (request) => {
648
+ if (!isInitialized) {
649
+ throw new Error('SDK not initialized. Call initialize() first.');
650
+ }
651
+ if (!transactions?.createTransaction) {
652
+ throw new Error('createTransaction method not available');
653
+ }
654
+ try {
655
+ console.log('🔄 Creating transaction with request:', request);
656
+ const result = await transactions.createTransaction(request);
657
+ // React Native specific: Handle signature URLs
658
+ if (result?.actionable?.actionUrl) {
659
+ try {
660
+ const { Linking } = require('react-native');
661
+ console.log('🔗 Opening signature URL:', result.actionable.actionUrl);
662
+ await Linking.openURL(result.actionable.actionUrl);
663
+ }
664
+ catch (linkingError) {
665
+ console.error('❌ Failed to open signature URL:', linkingError);
666
+ }
667
+ }
668
+ console.log('✅ Transaction created successfully:', result);
669
+ return result;
670
+ }
671
+ catch (error) {
672
+ console.error('❌ Failed to create transaction:', error);
673
+ throw error;
674
+ }
675
+ }, [transactions]);
676
+ const getTransactionById = react.useCallback(async (transactionId) => {
677
+ if (!isInitialized) {
678
+ throw new Error('SDK not initialized. Call initialize() first.');
679
+ }
680
+ if (!transactions?.getTransactionById) {
681
+ throw new Error('getTransactionById method not available');
682
+ }
683
+ try {
684
+ const result = await transactions.getTransactionById(transactionId);
685
+ console.log('✅ Transaction fetched successfully:', result);
686
+ return result;
687
+ }
688
+ catch (error) {
689
+ console.error('❌ Failed to fetch transaction:', error);
690
+ throw error;
691
+ }
692
+ }, [transactions]);
693
+ const getTransactionHistory = react.useCallback(async (filters) => {
694
+ if (!isInitialized) {
695
+ throw new Error('SDK not initialized. Call initialize() first.');
696
+ }
697
+ if (!transactions?.getTransactionHistory) {
698
+ console.warn('getTransactionHistory method not available');
699
+ return [];
700
+ }
701
+ try {
702
+ const result = await transactions.getTransactionHistory(filters);
703
+ console.log('✅ Transaction history fetched successfully:', result);
704
+ return result;
705
+ }
706
+ catch (error) {
707
+ console.error('❌ Failed to fetch transaction history:', error);
708
+ throw error;
709
+ }
710
+ }, [transactions]);
711
+ return {
712
+ createTransaction,
713
+ getTransactionById,
714
+ getTransactionHistory,
715
+ isAvailable: isInitialized && !!transactions,
716
+ };
717
+ };
718
+
719
+ const useBusiness = () => {
720
+ const { business, isInitialized } = usePersSDK();
721
+ const getActiveBusinesses = react.useCallback(async () => {
722
+ if (!isInitialized) {
723
+ throw new Error('SDK not initialized. Call initialize() first.');
724
+ }
725
+ if (!business?.getActiveBusinesses) {
726
+ console.warn('getActiveBusinesses method not available');
727
+ return [];
728
+ }
729
+ try {
730
+ const result = await business.getActiveBusinesses();
731
+ console.log('✅ Active businesses fetched successfully:', result);
732
+ return result;
733
+ }
734
+ catch (error) {
735
+ console.error('❌ Failed to fetch active businesses:', error);
736
+ throw error;
737
+ }
738
+ }, [business]);
739
+ const getAllBusinessTypes = react.useCallback(async () => {
740
+ if (!isInitialized) {
741
+ throw new Error('SDK not initialized. Call initialize() first.');
742
+ }
743
+ if (!business?.getAllBusinessTypes) {
744
+ console.warn('getAllBusinessTypes method not available');
745
+ return [];
746
+ }
747
+ try {
748
+ const result = await business.getAllBusinessTypes();
749
+ console.log('✅ Business types fetched successfully:', result);
750
+ return result;
751
+ }
752
+ catch (error) {
753
+ console.error('❌ Failed to fetch business types:', error);
754
+ throw error;
755
+ }
756
+ }, [business]);
757
+ const getBusinessById = react.useCallback(async (businessId) => {
758
+ if (!isInitialized) {
759
+ throw new Error('SDK not initialized. Call initialize() first.');
760
+ }
761
+ if (!business?.getBusinessById) {
762
+ throw new Error('getBusinessById method not available');
763
+ }
764
+ try {
765
+ const result = await business.getBusinessById(businessId);
766
+ console.log('✅ Business fetched successfully:', result);
767
+ return result;
768
+ }
769
+ catch (error) {
770
+ console.error('❌ Failed to fetch business:', error);
771
+ throw error;
772
+ }
773
+ }, [business]);
774
+ return {
775
+ getActiveBusinesses,
776
+ getAllBusinessTypes,
777
+ getBusinessById,
778
+ isAvailable: isInitialized && !!business,
779
+ };
780
+ };
781
+
782
+ const useCampaigns = () => {
783
+ const { campaigns, isInitialized, isAuthenticated } = usePersSDK();
784
+ const getActiveCampaigns = react.useCallback(async () => {
785
+ if (!isInitialized) {
786
+ throw new Error('SDK not initialized. Call initialize() first.');
787
+ }
788
+ if (!campaigns?.getActiveCampaigns) {
789
+ console.warn('getActiveCampaigns method not available');
790
+ return [];
791
+ }
792
+ try {
793
+ const result = await campaigns.getActiveCampaigns();
794
+ console.log('✅ Active campaigns fetched successfully:', result);
795
+ return result;
796
+ }
797
+ catch (error) {
798
+ console.error('❌ Failed to fetch active campaigns:', error);
799
+ throw error;
800
+ }
801
+ }, [campaigns]);
802
+ const getCampaignById = react.useCallback(async (campaignId) => {
803
+ if (!isInitialized) {
804
+ throw new Error('SDK not initialized. Call initialize() first.');
805
+ }
806
+ if (!campaigns?.getCampaignById) {
807
+ throw new Error('getCampaignById method not available');
808
+ }
809
+ try {
810
+ const result = await campaigns.getCampaignById(campaignId);
811
+ console.log('✅ Campaign fetched successfully:', result);
812
+ return result;
813
+ }
814
+ catch (error) {
815
+ console.error('❌ Failed to fetch campaign:', error);
816
+ throw error;
817
+ }
818
+ }, [campaigns]);
819
+ const claimCampaign = react.useCallback(async (request) => {
820
+ if (!isInitialized) {
821
+ throw new Error('SDK not initialized. Call initialize() first.');
822
+ }
823
+ if (!isAuthenticated) {
824
+ throw new Error('SDK not authenticated. claimCampaign requires authentication.');
825
+ }
826
+ if (!campaigns?.claimCampaign) {
827
+ throw new Error('claimCampaign method not available');
828
+ }
829
+ try {
830
+ console.log('🔄 Claiming campaign with request:', request);
831
+ const result = await campaigns.claimCampaign(request);
832
+ console.log('✅ Campaign claimed successfully:', result);
833
+ return result;
834
+ }
835
+ catch (error) {
836
+ console.error('❌ Failed to claim campaign:', error);
837
+ throw error;
838
+ }
839
+ }, [isInitialized, isAuthenticated, campaigns]);
840
+ const getClaimsForLoggedUser = react.useCallback(async () => {
841
+ if (!isInitialized) {
842
+ throw new Error('SDK not initialized. Call initialize() first.');
843
+ }
844
+ if (!isAuthenticated) {
845
+ console.warn('SDK not authenticated. getClaimsForLoggedUser requires authentication.');
846
+ return [];
847
+ }
848
+ if (!campaigns?.getClaimsForLoggedUser) {
849
+ console.warn('getClaimsForLoggedUser method not available');
850
+ return [];
851
+ }
852
+ try {
853
+ const result = await campaigns.getClaimsForLoggedUser();
854
+ console.log('✅ User claims fetched successfully:', result);
855
+ return result;
856
+ }
857
+ catch (error) {
858
+ console.error('❌ Failed to fetch user claims:', error);
859
+ throw error;
860
+ }
861
+ }, [isInitialized, isAuthenticated, campaigns]);
862
+ return {
863
+ getActiveCampaigns,
864
+ getCampaignById,
865
+ claimCampaign,
866
+ getClaimsForLoggedUser,
867
+ isAvailable: isInitialized && !!campaigns,
868
+ };
869
+ };
870
+
871
+ const useRedemptions = () => {
872
+ const { redemptions, isInitialized, isAuthenticated } = usePersSDK();
873
+ // Admin method: Create new redemption offers
874
+ const createRedemption = react.useCallback(async (redemptionData) => {
875
+ if (!isInitialized) {
876
+ throw new Error('SDK not initialized. Call initialize() first.');
877
+ }
878
+ if (!redemptions?.createRedemption) {
879
+ throw new Error('createRedemption method not available - admin access required');
880
+ }
881
+ try {
882
+ console.log('🔄 Creating redemption offer with data:', redemptionData);
883
+ const result = await redemptions.createRedemption(redemptionData);
884
+ console.log('✅ Redemption offer created successfully:', result);
885
+ return result;
886
+ }
887
+ catch (error) {
888
+ console.error('❌ Failed to create redemption offer:', error);
889
+ throw error;
890
+ }
891
+ }, [redemptions]);
892
+ const getActiveRedemptions = react.useCallback(async () => {
893
+ if (!isInitialized) {
894
+ throw new Error('SDK not initialized. Call initialize() first.');
895
+ }
896
+ if (!redemptions?.getActiveRedemptions) {
897
+ console.warn('getActiveRedemptions method not available');
898
+ return [];
899
+ }
900
+ try {
901
+ const result = await redemptions.getActiveRedemptions();
902
+ console.log('✅ Active redemptions fetched successfully:', result);
903
+ return result;
904
+ }
905
+ catch (error) {
906
+ console.error('❌ Failed to fetch active redemptions:', error);
907
+ throw error;
908
+ }
909
+ }, [redemptions]);
910
+ const getUserRedeems = react.useCallback(async () => {
911
+ if (!isInitialized) {
912
+ throw new Error('SDK not initialized. Call initialize() first.');
913
+ }
914
+ if (!isAuthenticated) {
915
+ console.warn('SDK not authenticated. getUserRedeems requires authentication.');
916
+ return [];
917
+ }
918
+ if (!redemptions?.getUserRedeems) {
919
+ console.warn('getUserRedeems method not available');
920
+ return [];
921
+ }
922
+ try {
923
+ const result = await redemptions.getUserRedeems();
924
+ console.log('✅ User redemptions fetched successfully:', result);
925
+ return result;
926
+ }
927
+ catch (error) {
928
+ console.error('❌ Failed to fetch user redemptions:', error);
929
+ throw error;
930
+ }
931
+ }, [isInitialized, isAuthenticated, redemptions]);
932
+ const redeemRedemption = react.useCallback(async (redemptionId) => {
933
+ if (!isInitialized) {
934
+ throw new Error('SDK not initialized. Call initialize() first.');
935
+ }
936
+ if (!isAuthenticated) {
937
+ throw new Error('SDK not authenticated. redeemRedemption requires authentication.');
938
+ }
939
+ if (!redemptions?.redeemRedemption) {
940
+ throw new Error('redeemRedemption method not available');
941
+ }
942
+ try {
943
+ console.log('🔄 Redeeming redemption:', redemptionId);
944
+ const result = await redemptions.redeemRedemption(redemptionId);
945
+ // React Native specific: Handle signature URLs for redemptions
946
+ if (result?.actionable?.actionUrl) {
947
+ try {
948
+ const { Linking } = require('react-native');
949
+ console.log('🔗 Opening redemption signature URL:', result.actionable.actionUrl);
950
+ await Linking.openURL(result.actionable.actionUrl);
951
+ }
952
+ catch (linkingError) {
953
+ console.error('❌ Failed to open redemption signature URL:', linkingError);
954
+ }
955
+ }
956
+ console.log('✅ Redemption processed successfully:', result);
957
+ return result;
958
+ }
959
+ catch (error) {
960
+ console.error('❌ Failed to redeem redemption:', error);
961
+ throw error;
962
+ }
963
+ }, [isInitialized, isAuthenticated, redemptions]);
964
+ const getRedemptionById = react.useCallback(async (redemptionId) => {
965
+ if (!isInitialized) {
966
+ throw new Error('SDK not initialized. Call initialize() first.');
967
+ }
968
+ if (!redemptions?.getRedemptionById) {
969
+ throw new Error('getRedemptionById method not available');
970
+ }
971
+ try {
972
+ const result = await redemptions.getRedemptionById(redemptionId);
973
+ console.log('✅ Redemption fetched successfully:', result);
974
+ return result;
975
+ }
976
+ catch (error) {
977
+ console.error('❌ Failed to fetch redemption:', error);
978
+ throw error;
979
+ }
980
+ }, [redemptions]);
981
+ return {
982
+ createRedemption,
983
+ getActiveRedemptions,
984
+ getUserRedeems,
985
+ redeemRedemption,
986
+ getRedemptionById,
987
+ isAvailable: isInitialized && !!redemptions,
988
+ };
989
+ };
990
+
991
+ const useWeb3 = () => {
992
+ const { web3, isInitialized, isAuthenticated, accountAddress } = usePersSDK();
993
+ if (!isAuthenticated && isInitialized) {
994
+ console.warn('SDK not authenticated. Some web3 operations may fail.');
995
+ }
996
+ const getTokenBalance = react.useCallback(async (request) => {
997
+ if (!isInitialized) {
998
+ throw new Error('SDK not initialized. Call initialize() first.');
999
+ }
1000
+ if (!web3?.getTokenBalance) {
1001
+ throw new Error('getTokenBalance method not available');
1002
+ }
1003
+ try {
1004
+ const result = await web3.getTokenBalance(request);
1005
+ console.log('✅ Token balance fetched successfully:', result);
1006
+ return result;
1007
+ }
1008
+ catch (error) {
1009
+ console.error('❌ Failed to fetch token balance:', error);
1010
+ throw error;
1011
+ }
1012
+ }, [web3]);
1013
+ const getTokenCollection = react.useCallback(async (request) => {
1014
+ if (!isInitialized) {
1015
+ throw new Error('SDK not initialized. Call initialize() first.');
1016
+ }
1017
+ if (!web3?.getTokenCollection) {
1018
+ console.warn('getTokenCollection method not available');
1019
+ return [];
1020
+ }
1021
+ try {
1022
+ const result = await web3.getTokenCollection(request);
1023
+ console.log('✅ Token collection fetched successfully:', result);
1024
+ return result;
1025
+ }
1026
+ catch (error) {
1027
+ console.error('❌ Failed to fetch token collection:', error);
1028
+ throw error;
1029
+ }
1030
+ }, [web3]);
1031
+ const getWalletInfo = react.useCallback(async () => {
1032
+ if (!isInitialized) {
1033
+ throw new Error('SDK not initialized. Call initialize() first.');
1034
+ }
1035
+ if (!accountAddress) {
1036
+ console.warn('No account address available');
1037
+ return null;
1038
+ }
1039
+ return {
1040
+ address: accountAddress,
1041
+ isConnected: !!accountAddress,
1042
+ };
1043
+ }, [isInitialized, accountAddress]);
1044
+ return {
1045
+ getTokenBalance,
1046
+ getTokenCollection,
1047
+ getWalletInfo,
1048
+ accountAddress: isInitialized ? accountAddress : null,
1049
+ isAvailable: isInitialized && !!web3,
1050
+ };
1051
+ };
1052
+
1053
+ // Initialize React Native polyfills automatically
1054
+ // TEMPORARY: Minimal exports to isolate the .from() error
1055
+ console.log('🔍 [DEBUG] Loading React Native SDK...');
1056
+ console.log('🔍 [DEBUG] Auth providers loaded successfully');
1057
+ console.log('🔍 [DEBUG] React Native SDK loaded with full exports including useWeb3');
1058
+ // Note: For types and DTOs, import directly from @explorins/pers-shared
1059
+ // This maintains clean separation and avoids circular dependencies
1060
+ // Example: import { TokenDTO, BusinessDTO } from '@explorins/pers-shared';
1061
+
1062
+ exports.BaseReactNativeAuthProvider = BaseReactNativeAuthProvider;
1063
+ exports.PersSDKProvider = PersSDKProvider;
1064
+ exports.ReactNativeAuthProvider = ReactNativeAuthProvider;
1065
+ exports.ReactNativeHttpClient = ReactNativeHttpClient;
1066
+ exports.SecureReactNativeAuthProvider = SecureReactNativeAuthProvider;
1067
+ exports.initializeReactNativePolyfills = initializeReactNativePolyfills;
1068
+ exports.isReactNative = isReactNative;
1069
+ exports.useAuth = useAuth;
1070
+ exports.useBusiness = useBusiness;
1071
+ exports.useCampaigns = useCampaigns;
1072
+ exports.usePersSDK = usePersSDK;
1073
+ exports.useRedemptions = useRedemptions;
1074
+ exports.useTokens = useTokens;
1075
+ exports.useTransactions = useTransactions;
1076
+ exports.useWeb3 = useWeb3;
1077
+ //# sourceMappingURL=index.js.map