@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react-native-http-client.d.ts","sourceRoot":"","sources":["../../src/providers/react-native-http-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;CACzD;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAC1D,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtE,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC9D;AAED,qBAAa,qBAAsB,YAAW,UAAU;IACtD,OAAO,CAAC,OAAO,CAAC,CAAS;gBAEb,OAAO,CAAC,EAAE,MAAM;IAItB,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAI/D,IAAI,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAI5E,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAI3E,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;YAI1D,OAAO;IAsErB,OAAO,CAAC,QAAQ;CAcjB"}
@@ -0,0 +1,94 @@
1
+ /**
2
+ * HTTP Client implementation for React Native
3
+ *
4
+ * This implementation properly implements the core SDK's HttpClient interface
5
+ * and uses fetch API which is available in React Native.
6
+ */
7
+ export class ReactNativeHttpClient {
8
+ constructor(baseURL) {
9
+ this.baseURL = baseURL;
10
+ }
11
+ async get(url, options) {
12
+ return this.request('GET', url, undefined, options);
13
+ }
14
+ async post(url, body, options) {
15
+ return this.request('POST', url, body, options);
16
+ }
17
+ async put(url, body, options) {
18
+ return this.request('PUT', url, body, options);
19
+ }
20
+ async delete(url, options) {
21
+ return this.request('DELETE', url, undefined, options);
22
+ }
23
+ async request(method, url, body, options) {
24
+ const fullUrl = this.buildUrl(url, options?.params);
25
+ const config = {
26
+ method,
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ ...options?.headers,
30
+ },
31
+ };
32
+ // Add timeout if specified
33
+ if (options?.timeout) {
34
+ const controller = new AbortController();
35
+ config.signal = controller.signal;
36
+ setTimeout(() => controller.abort(), options.timeout);
37
+ }
38
+ // Add body for POST/PUT requests
39
+ if (body && (method === 'POST' || method === 'PUT')) {
40
+ config.body = JSON.stringify(body);
41
+ }
42
+ try {
43
+ const response = await fetch(fullUrl, config);
44
+ if (!response.ok) {
45
+ // Try to get error details from response
46
+ let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
47
+ try {
48
+ const errorBody = await response.text();
49
+ if (errorBody) {
50
+ errorMessage += ` - ${errorBody}`;
51
+ }
52
+ }
53
+ catch (e) {
54
+ // Ignore errors when reading error body
55
+ }
56
+ throw new Error(errorMessage);
57
+ }
58
+ // Handle different response types
59
+ switch (options?.responseType) {
60
+ case 'text':
61
+ return response.text();
62
+ case 'blob':
63
+ return response.blob();
64
+ case 'arraybuffer':
65
+ return response.arrayBuffer();
66
+ case 'json':
67
+ default:
68
+ // Check if response has content
69
+ const contentLength = response.headers.get('content-length');
70
+ if (contentLength === '0' || response.status === 204) {
71
+ return undefined;
72
+ }
73
+ return response.json();
74
+ }
75
+ }
76
+ catch (error) {
77
+ if (error instanceof Error && error.name === 'AbortError') {
78
+ throw new Error(`Request timeout after ${options?.timeout}ms`);
79
+ }
80
+ throw error;
81
+ }
82
+ }
83
+ buildUrl(url, params) {
84
+ const fullUrl = this.baseURL ? `${this.baseURL}${url}` : url;
85
+ if (!params || Object.keys(params).length === 0) {
86
+ return fullUrl;
87
+ }
88
+ const urlObj = new URL(fullUrl);
89
+ Object.entries(params).forEach(([key, value]) => {
90
+ urlObj.searchParams.append(key, value);
91
+ });
92
+ return urlObj.toString();
93
+ }
94
+ }
package/package.json ADDED
@@ -0,0 +1,157 @@
1
+ {
2
+ "name": "@explorins/pers-sdk-react-native",
3
+ "version": "1.3.2",
4
+ "description": "React Native SDK for PERS Platform - Tourism Loyalty System",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc && rollup -c --bundleConfigAsCjs",
9
+ "dev": "tsc --watch",
10
+ "clean": "rimraf dist",
11
+ "prepublishOnly": "npm run clean && npm run build"
12
+ },
13
+ "keywords": [
14
+ "pers",
15
+ "sdk",
16
+ "react-native",
17
+ "tourism",
18
+ "loyalty",
19
+ "blockchain",
20
+ "web3"
21
+ ],
22
+ "author": "eXplorins",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@explorins/pers-sdk": "^1.3.2",
26
+ "@explorins/pers-shared": "^2.1.40",
27
+ "buffer": "^6.0.3",
28
+ "ethers": "^6.15.0",
29
+ "web3": "^4.16.0"
30
+ },
31
+ "browser": {
32
+ "crypto": false,
33
+ "url": false,
34
+ "http": false,
35
+ "https": false,
36
+ "zlib": false,
37
+ "stream": false,
38
+ "assert": false,
39
+ "path": false,
40
+ "fs": false,
41
+ "os": false,
42
+ "readable-stream": false,
43
+ "util": false,
44
+ "events": false,
45
+ "net": false,
46
+ "tls": false,
47
+ "child_process": false,
48
+ "pngjs": false,
49
+ "pngjs/lib/bitmapper": false,
50
+ "pngjs/lib/parser-async": false,
51
+ "pngjs/lib/parser-sync": false,
52
+ "./bitmapper": false,
53
+ "hash-base": false,
54
+ "@ethereumjs/common": false,
55
+ "@ethereumjs/tx": false,
56
+ "@ethereumjs/util": false,
57
+ "stream-browserify": false,
58
+ "crypto-browserify": false,
59
+ "inherits": false,
60
+ "safe-buffer": false,
61
+ "string_decoder": false,
62
+ "process-nextick-args": false,
63
+ "isarray": false,
64
+ "core-util-is": false,
65
+ "util-deprecate": false,
66
+ "ethereum-cryptography": false,
67
+ "keccak": false,
68
+ "secp256k1": false,
69
+ "scrypt-js": false,
70
+ "bech32": false,
71
+ "ws": false,
72
+ "xhr2-cookies": false,
73
+ "aes-js": false,
74
+ "@ethersproject/sha2": false,
75
+ "@ethersproject/pbkdf2": false,
76
+ "@ethersproject/scrypt": false
77
+ },
78
+ "peerDependencies": {
79
+ "react": ">=16.8.0",
80
+ "react-native": ">=0.60.0"
81
+ },
82
+ "peerDependenciesMeta": {
83
+ "react-native-keychain": {
84
+ "optional": true
85
+ },
86
+ "@react-native-async-storage/async-storage": {
87
+ "optional": false
88
+ },
89
+ "react-native-get-random-values": {
90
+ "optional": true
91
+ },
92
+ "react-native-url-polyfill": {
93
+ "optional": true
94
+ },
95
+ "react-native-polyfill-globals": {
96
+ "optional": true
97
+ },
98
+ "web-streams-polyfill": {
99
+ "optional": true
100
+ }
101
+ },
102
+ "overrides": {
103
+ "readable-stream": false,
104
+ "@ethereumjs/common": false,
105
+ "@ethereumjs/util": false,
106
+ "@ethereumjs/rlp": false,
107
+ "@ethereumjs/tx": false,
108
+ "stream": false,
109
+ "util": false,
110
+ "events": false,
111
+ "crypto": false,
112
+ "fs": false,
113
+ "path": false,
114
+ "os": false,
115
+ "net": false,
116
+ "tls": false,
117
+ "child_process": false,
118
+ "hash-base": false,
119
+ "inherits": false,
120
+ "safe-buffer": false,
121
+ "string_decoder": false,
122
+ "process-nextick-args": false,
123
+ "isarray": false,
124
+ "core-util-is": false,
125
+ "util-deprecate": false,
126
+ "ethereum-cryptography": false,
127
+ "keccak": false,
128
+ "secp256k1": false,
129
+ "scrypt-js": false,
130
+ "bech32": false,
131
+ "ws": false,
132
+ "xhr2-cookies": false,
133
+ "aes-js": false,
134
+ "@ethersproject/sha2": false,
135
+ "@ethersproject/pbkdf2": false,
136
+ "@ethersproject/scrypt": false
137
+ },
138
+ "devDependencies": {
139
+ "@react-native-async-storage/async-storage": "^1.19.0",
140
+ "@types/react": "^19.1.1",
141
+ "@types/react-native": "^0.72.8",
142
+ "rimraf": "^5.0.0",
143
+ "rollup": "^4.0.0",
144
+ "rollup-plugin-typescript2": "^0.36.0",
145
+ "typescript": "^5.2.0"
146
+ },
147
+ "files": [
148
+ "dist/**/*",
149
+ "src/**/*",
150
+ "README.md"
151
+ ],
152
+ "repository": {
153
+ "type": "git",
154
+ "url": "git+https://github.com/eXplorins/pers-sdk.git",
155
+ "directory": "packages/pers-sdk-react-native"
156
+ }
157
+ }
@@ -0,0 +1,8 @@
1
+ // Export all hooks (only hooks, no providers to avoid circular dependency)
2
+ export { useAuth } from './useAuth';
3
+ export { useTokens } from './useTokens';
4
+ export { useTransactions } from './useTransactions';
5
+ export { useBusiness } from './useBusiness';
6
+ export { useCampaigns } from './useCampaigns';
7
+ export { useRedemptions } from './useRedemptions';
8
+ export { useWeb3 } from './useWeb3';
@@ -0,0 +1,43 @@
1
+ import { useCallback } from 'react';
2
+ import { usePersSDK } from '../providers/PersSDKProvider';
3
+
4
+ export interface AuthHook {
5
+ // State
6
+ isInitialized: boolean;
7
+ isAuthenticated: boolean;
8
+ user: any | null;
9
+ accountAddress: string | null;
10
+
11
+ // Actions
12
+ initialize: (config: any) => Promise<void>;
13
+ login: (jwtToken: string, userType?: 'user' | 'admin') => Promise<any>;
14
+ loginWithRawData: (rawUserData: any) => Promise<any>;
15
+ logout: () => Promise<void>;
16
+ }
17
+
18
+ export const useAuth = (): AuthHook => {
19
+ const {
20
+ isInitialized,
21
+ isAuthenticated,
22
+ user,
23
+ accountAddress,
24
+ initialize,
25
+ login,
26
+ loginWithRawData,
27
+ logout,
28
+ } = usePersSDK();
29
+
30
+ return {
31
+ // State
32
+ isInitialized,
33
+ isAuthenticated,
34
+ user,
35
+ accountAddress,
36
+
37
+ // Actions
38
+ initialize,
39
+ login,
40
+ loginWithRawData,
41
+ logout,
42
+ };
43
+ };
@@ -0,0 +1,69 @@
1
+ import { useCallback } from 'react';
2
+ import { usePersSDK } from '../providers/PersSDKProvider';
3
+
4
+ export const useBusiness = () => {
5
+ const { business, isInitialized } = usePersSDK();
6
+
7
+ const getActiveBusinesses = useCallback(async () => {
8
+ if (!isInitialized) {
9
+ throw new Error('SDK not initialized. Call initialize() first.');
10
+ }
11
+ if (!business?.getActiveBusinesses) {
12
+ console.warn('getActiveBusinesses method not available');
13
+ return [];
14
+ }
15
+
16
+ try {
17
+ const result = await business.getActiveBusinesses();
18
+ console.log('✅ Active businesses fetched successfully:', result);
19
+ return result;
20
+ } catch (error) {
21
+ console.error('❌ Failed to fetch active businesses:', error);
22
+ throw error;
23
+ }
24
+ }, [business]);
25
+
26
+ const getAllBusinessTypes = useCallback(async () => {
27
+ if (!isInitialized) {
28
+ throw new Error('SDK not initialized. Call initialize() first.');
29
+ }
30
+ if (!business?.getAllBusinessTypes) {
31
+ console.warn('getAllBusinessTypes method not available');
32
+ return [];
33
+ }
34
+
35
+ try {
36
+ const result = await business.getAllBusinessTypes();
37
+ console.log('✅ Business types fetched successfully:', result);
38
+ return result;
39
+ } catch (error) {
40
+ console.error('❌ Failed to fetch business types:', error);
41
+ throw error;
42
+ }
43
+ }, [business]);
44
+
45
+ const getBusinessById = useCallback(async (businessId: string) => {
46
+ if (!isInitialized) {
47
+ throw new Error('SDK not initialized. Call initialize() first.');
48
+ }
49
+ if (!business?.getBusinessById) {
50
+ throw new Error('getBusinessById method not available');
51
+ }
52
+
53
+ try {
54
+ const result = await business.getBusinessById(businessId);
55
+ console.log('✅ Business fetched successfully:', result);
56
+ return result;
57
+ } catch (error) {
58
+ console.error('❌ Failed to fetch business:', error);
59
+ throw error;
60
+ }
61
+ }, [business]);
62
+
63
+ return {
64
+ getActiveBusinesses,
65
+ getAllBusinessTypes,
66
+ getBusinessById,
67
+ isAvailable: isInitialized && !!business,
68
+ };
69
+ };
@@ -0,0 +1,96 @@
1
+ import { useCallback } from 'react';
2
+ import { usePersSDK } from '../providers/PersSDKProvider';
3
+
4
+ export const useCampaigns = () => {
5
+ const { campaigns, isInitialized, isAuthenticated } = usePersSDK();
6
+
7
+ const getActiveCampaigns = useCallback(async () => {
8
+ if (!isInitialized) {
9
+ throw new Error('SDK not initialized. Call initialize() first.');
10
+ }
11
+ if (!campaigns?.getActiveCampaigns) {
12
+ console.warn('getActiveCampaigns method not available');
13
+ return [];
14
+ }
15
+
16
+ try {
17
+ const result = await campaigns.getActiveCampaigns();
18
+ console.log('✅ Active campaigns fetched successfully:', result);
19
+ return result;
20
+ } catch (error) {
21
+ console.error('❌ Failed to fetch active campaigns:', error);
22
+ throw error;
23
+ }
24
+ }, [campaigns]);
25
+
26
+ const getCampaignById = useCallback(async (campaignId: string) => {
27
+ if (!isInitialized) {
28
+ throw new Error('SDK not initialized. Call initialize() first.');
29
+ }
30
+ if (!campaigns?.getCampaignById) {
31
+ throw new Error('getCampaignById method not available');
32
+ }
33
+
34
+ try {
35
+ const result = await campaigns.getCampaignById(campaignId);
36
+ console.log('✅ Campaign fetched successfully:', result);
37
+ return result;
38
+ } catch (error) {
39
+ console.error('❌ Failed to fetch campaign:', error);
40
+ throw error;
41
+ }
42
+ }, [campaigns]);
43
+
44
+ const claimCampaign = useCallback(async (request: any) => {
45
+ if (!isInitialized) {
46
+ throw new Error('SDK not initialized. Call initialize() first.');
47
+ }
48
+ if (!isAuthenticated) {
49
+ throw new Error('SDK not authenticated. claimCampaign requires authentication.');
50
+ }
51
+ if (!campaigns?.claimCampaign) {
52
+ throw new Error('claimCampaign method not available');
53
+ }
54
+
55
+ try {
56
+ console.log('🔄 Claiming campaign with request:', request);
57
+ const result = await campaigns.claimCampaign(request);
58
+ console.log('✅ Campaign claimed successfully:', result);
59
+ return result;
60
+ } catch (error) {
61
+ console.error('❌ Failed to claim campaign:', error);
62
+ throw error;
63
+ }
64
+ }, [isInitialized, isAuthenticated, campaigns]);
65
+
66
+ const getClaimsForLoggedUser = useCallback(async () => {
67
+ if (!isInitialized) {
68
+ throw new Error('SDK not initialized. Call initialize() first.');
69
+ }
70
+ if (!isAuthenticated) {
71
+ console.warn('SDK not authenticated. getClaimsForLoggedUser requires authentication.');
72
+ return [];
73
+ }
74
+ if (!campaigns?.getClaimsForLoggedUser) {
75
+ console.warn('getClaimsForLoggedUser method not available');
76
+ return [];
77
+ }
78
+
79
+ try {
80
+ const result = await campaigns.getClaimsForLoggedUser();
81
+ console.log('✅ User claims fetched successfully:', result);
82
+ return result;
83
+ } catch (error) {
84
+ console.error('❌ Failed to fetch user claims:', error);
85
+ throw error;
86
+ }
87
+ }, [isInitialized, isAuthenticated, campaigns]);
88
+
89
+ return {
90
+ getActiveCampaigns,
91
+ getCampaignById,
92
+ claimCampaign,
93
+ getClaimsForLoggedUser,
94
+ isAvailable: isInitialized && !!campaigns,
95
+ };
96
+ };
@@ -0,0 +1,129 @@
1
+ import { useCallback } from 'react';
2
+ import { usePersSDK } from '../providers/PersSDKProvider';
3
+
4
+ export const useRedemptions = () => {
5
+ const { redemptions, isInitialized, isAuthenticated } = usePersSDK();
6
+
7
+ // Admin method: Create new redemption offers
8
+ const createRedemption = useCallback(async (redemptionData: any) => {
9
+ if (!isInitialized) {
10
+ throw new Error('SDK not initialized. Call initialize() first.');
11
+ }
12
+ if (!redemptions?.createRedemption) {
13
+ throw new Error('createRedemption method not available - admin access required');
14
+ }
15
+
16
+ try {
17
+ console.log('🔄 Creating redemption offer with data:', redemptionData);
18
+ const result = await redemptions.createRedemption(redemptionData);
19
+ console.log('✅ Redemption offer created successfully:', result);
20
+ return result;
21
+ } catch (error) {
22
+ console.error('❌ Failed to create redemption offer:', error);
23
+ throw error;
24
+ }
25
+ }, [redemptions]);
26
+
27
+ const getActiveRedemptions = useCallback(async () => {
28
+ if (!isInitialized) {
29
+ throw new Error('SDK not initialized. Call initialize() first.');
30
+ }
31
+ if (!redemptions?.getActiveRedemptions) {
32
+ console.warn('getActiveRedemptions method not available');
33
+ return [];
34
+ }
35
+
36
+ try {
37
+ const result = await redemptions.getActiveRedemptions();
38
+ console.log('✅ Active redemptions fetched successfully:', result);
39
+ return result;
40
+ } catch (error) {
41
+ console.error('❌ Failed to fetch active redemptions:', error);
42
+ throw error;
43
+ }
44
+ }, [redemptions]);
45
+
46
+ const getUserRedeems = useCallback(async () => {
47
+ if (!isInitialized) {
48
+ throw new Error('SDK not initialized. Call initialize() first.');
49
+ }
50
+ if (!isAuthenticated) {
51
+ console.warn('SDK not authenticated. getUserRedeems requires authentication.');
52
+ return [];
53
+ }
54
+ if (!redemptions?.getUserRedeems) {
55
+ console.warn('getUserRedeems method not available');
56
+ return [];
57
+ }
58
+
59
+ try {
60
+ const result = await redemptions.getUserRedeems();
61
+ console.log('✅ User redemptions fetched successfully:', result);
62
+ return result;
63
+ } catch (error) {
64
+ console.error('❌ Failed to fetch user redemptions:', error);
65
+ throw error;
66
+ }
67
+ }, [isInitialized, isAuthenticated, redemptions]);
68
+
69
+ const redeemRedemption = useCallback(async (redemptionId: string) => {
70
+ if (!isInitialized) {
71
+ throw new Error('SDK not initialized. Call initialize() first.');
72
+ }
73
+ if (!isAuthenticated) {
74
+ throw new Error('SDK not authenticated. redeemRedemption requires authentication.');
75
+ }
76
+ if (!redemptions?.redeemRedemption) {
77
+ throw new Error('redeemRedemption method not available');
78
+ }
79
+
80
+ try {
81
+ console.log('🔄 Redeeming redemption:', redemptionId);
82
+ const result = await redemptions.redeemRedemption(redemptionId);
83
+
84
+ // React Native specific: Handle signature URLs for redemptions
85
+ if (result?.actionable?.actionUrl) {
86
+ try {
87
+ const { Linking } = require('react-native');
88
+ console.log('🔗 Opening redemption signature URL:', result.actionable.actionUrl);
89
+ await Linking.openURL(result.actionable.actionUrl);
90
+ } catch (linkingError) {
91
+ console.error('❌ Failed to open redemption signature URL:', linkingError);
92
+ }
93
+ }
94
+
95
+ console.log('✅ Redemption processed successfully:', result);
96
+ return result;
97
+ } catch (error) {
98
+ console.error('❌ Failed to redeem redemption:', error);
99
+ throw error;
100
+ }
101
+ }, [isInitialized, isAuthenticated, redemptions]);
102
+
103
+ const getRedemptionById = useCallback(async (redemptionId: string) => {
104
+ if (!isInitialized) {
105
+ throw new Error('SDK not initialized. Call initialize() first.');
106
+ }
107
+ if (!redemptions?.getRedemptionById) {
108
+ throw new Error('getRedemptionById method not available');
109
+ }
110
+
111
+ try {
112
+ const result = await redemptions.getRedemptionById(redemptionId);
113
+ console.log('✅ Redemption fetched successfully:', result);
114
+ return result;
115
+ } catch (error) {
116
+ console.error('❌ Failed to fetch redemption:', error);
117
+ throw error;
118
+ }
119
+ }, [redemptions]);
120
+
121
+ return {
122
+ createRedemption,
123
+ getActiveRedemptions,
124
+ getUserRedeems,
125
+ redeemRedemption,
126
+ getRedemptionById,
127
+ isAvailable: isInitialized && !!redemptions,
128
+ };
129
+ };
@@ -0,0 +1,53 @@
1
+ import { useCallback } from 'react';
2
+ import { usePersSDK } from '../providers/PersSDKProvider';
3
+
4
+ export const useTokens = () => {
5
+ const { tokens, isInitialized, isAuthenticated } = usePersSDK();
6
+
7
+ if (!isAuthenticated && isInitialized) {
8
+ console.warn('SDK not authenticated. Some token operations may fail.');
9
+ }
10
+
11
+ const getTokens = useCallback(async () => {
12
+ if (!isInitialized) {
13
+ throw new Error('SDK not initialized. Call initialize() first.');
14
+ }
15
+ if (!tokens?.getTokens) {
16
+ console.warn('getTokens method not available');
17
+ return [];
18
+ }
19
+
20
+ try {
21
+ const result = await tokens.getTokens();
22
+ console.log('✅ Tokens fetched successfully:', result);
23
+ return result;
24
+ } catch (error) {
25
+ console.error('❌ Failed to fetch tokens:', error);
26
+ throw error;
27
+ }
28
+ }, [tokens]);
29
+
30
+ const getTokenById = useCallback(async (tokenId: string) => {
31
+ if (!isInitialized) {
32
+ throw new Error('SDK not initialized. Call initialize() first.');
33
+ }
34
+ if (!tokens?.getTokenById) {
35
+ throw new Error('getTokenById method not available');
36
+ }
37
+
38
+ try {
39
+ const result = await tokens.getTokenById(tokenId);
40
+ console.log('✅ Token fetched successfully:', result);
41
+ return result;
42
+ } catch (error) {
43
+ console.error('❌ Failed to fetch token:', error);
44
+ throw error;
45
+ }
46
+ }, [tokens]);
47
+
48
+ return {
49
+ getTokens,
50
+ getTokenById,
51
+ isAvailable: isInitialized && !!tokens,
52
+ };
53
+ };