@explorins/pers-sdk-react-native 2.3.6 → 2.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1266 -1244
  3. package/dist/__tests__/PersSDKProvider.test.js +33 -0
  4. package/dist/hooks/useBusiness.d.ts +2 -2
  5. package/dist/hooks/useBusiness.d.ts.map +1 -1
  6. package/dist/hooks/useBusiness.js +2 -2
  7. package/dist/hooks/useIPFSUrl.d.ts +3 -3
  8. package/dist/hooks/useIPFSUrl.d.ts.map +1 -1
  9. package/dist/hooks/useIPFSUrl.js +7 -7
  10. package/dist/hooks/useTransactions.d.ts.map +1 -1
  11. package/dist/hooks/useTransactions.js +13 -5
  12. package/dist/hooks/useWeb3.js +4 -4
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2412 -492
  16. package/dist/index.js.map +1 -1
  17. package/dist/providers/PersSDKProvider.d.ts +4 -0
  18. package/dist/providers/PersSDKProvider.d.ts.map +1 -1
  19. package/dist/providers/PersSDKProvider.js +14 -0
  20. package/dist/providers/react-native-http-client.d.ts +2 -0
  21. package/dist/providers/react-native-http-client.d.ts.map +1 -1
  22. package/dist/providers/react-native-http-client.js +5 -2
  23. package/dist/storage/rn-secure-storage.d.ts.map +1 -1
  24. package/dist/storage/rn-secure-storage.js +21 -8
  25. package/package.json +3 -3
  26. package/src/__tests__/PersSDKProvider.test.tsx +484 -420
  27. package/src/__tests__/setup.ts +40 -40
  28. package/src/hooks/index.ts +60 -60
  29. package/src/hooks/useAnalytics.ts +327 -327
  30. package/src/hooks/useAuth.ts +265 -265
  31. package/src/hooks/useBookings.ts +191 -191
  32. package/src/hooks/useBusiness.ts +251 -251
  33. package/src/hooks/useCampaigns.ts +500 -500
  34. package/src/hooks/useDonations.ts +66 -66
  35. package/src/hooks/useEvents.ts +372 -372
  36. package/src/hooks/useFiles.ts +155 -155
  37. package/src/hooks/useIPFSUrl.ts +192 -192
  38. package/src/hooks/usePurchases.ts +65 -65
  39. package/src/hooks/useRedemptions.ts +467 -467
  40. package/src/hooks/useTenants.ts +72 -72
  41. package/src/hooks/useTokenBalances.ts +385 -385
  42. package/src/hooks/useTokens.ts +313 -313
  43. package/src/hooks/useTransactionSigner.ts +611 -611
  44. package/src/hooks/useTransactions.ts +299 -290
  45. package/src/hooks/useTriggerSources.ts +301 -301
  46. package/src/hooks/useUserStatus.ts +61 -61
  47. package/src/hooks/useUsers.ts +167 -167
  48. package/src/hooks/useWeb3.ts +355 -355
  49. package/src/index.ts +777 -774
  50. package/src/polyfills/index.ts +160 -160
  51. package/src/polyfills/web3-polyfills.ts +97 -97
  52. package/src/providers/PersSDKProvider.tsx +393 -374
  53. package/src/providers/react-native-auth-provider.ts +110 -110
  54. package/src/providers/react-native-http-client.ts +150 -145
  55. package/src/providers/rn-dpop-provider.ts +190 -190
  56. package/src/storage/async-storage-token-storage.ts +185 -185
  57. package/src/storage/rn-secure-storage.ts +182 -170
  58. package/src/types/react-native-globals.d.ts +45 -45
  59. package/src/utils/index.ts +8 -8
  60. package/src/utils/platform-detection.ts +86 -86
  61. package/dist/index-CzLxqePZ.js +0 -7717
  62. package/dist/index-CzLxqePZ.js.map +0 -1
@@ -1,190 +1,190 @@
1
- import { Platform } from 'react-native';
2
- import { Buffer } from 'buffer';
3
- import { DPoPCryptoProvider, DPoPKeyPair } from '@explorins/pers-sdk/core';
4
-
5
- // Lazy-loaded crypto module - initialized on first use to avoid native module timing issues
6
- let _crypto: any = null;
7
- let _cryptoInitialized = false;
8
-
9
- /**
10
- * Lazily load the crypto module.
11
- *
12
- * Supports customer pre-initialization via global.__QuickCrypto for environments
13
- * where native module timing is unpredictable (e.g., certain React Native setups).
14
- *
15
- * @returns The crypto module or null if unavailable
16
- */
17
- function getCrypto(): any {
18
- if (_cryptoInitialized) {
19
- return _crypto;
20
- }
21
-
22
- _cryptoInitialized = true;
23
-
24
- if (Platform.OS === 'web') {
25
- // On Web, we shouldn't be using this provider (Core SDK has WebDPoPProvider)
26
- _crypto = {
27
- generateKeyPair: () => { throw new Error('ReactNativeDPoPProvider not supported on Web'); },
28
- randomUUID: () => globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random()}`
29
- };
30
- return _crypto;
31
- }
32
-
33
- // Check for customer pre-initialized global (for native module timing issues)
34
- if (typeof global !== 'undefined' && (global as any).__QuickCrypto) {
35
- _crypto = (global as any).__QuickCrypto;
36
- return _crypto;
37
- }
38
-
39
- // Standard lazy load
40
- try {
41
- _crypto = require('react-native-quick-crypto').default || require('react-native-quick-crypto');
42
- } catch (e) {
43
- console.warn('ReactNativeDPoPProvider: Failed to load react-native-quick-crypto.', e);
44
- console.warn('Tip: If you encounter timing issues, pre-initialize in index.js: global.__QuickCrypto = require("react-native-quick-crypto")');
45
- _crypto = null;
46
- }
47
-
48
- return _crypto;
49
- }
50
-
51
- export class ReactNativeDPoPProvider implements DPoPCryptoProvider {
52
- /**
53
- * Generates a new key pair (ES256 recommended)
54
- *
55
- * Uses WebCrypto API (crypto.subtle) for cross-platform compatibility.
56
- * Falls back to Node.js crypto API on iOS if needed.
57
- */
58
- async generateKeyPair(options?: { extractable?: boolean }): Promise<DPoPKeyPair> {
59
- const crypto = getCrypto();
60
- if (!crypto) {
61
- throw new Error('Crypto module not available. Install react-native-quick-crypto or pre-initialize global.__QuickCrypto');
62
- }
63
-
64
- // Try WebCrypto API first (works on both iOS and Android)
65
- if (crypto.subtle) {
66
- try {
67
- const keyPair = await crypto.subtle.generateKey(
68
- { name: 'ECDSA', namedCurve: 'P-256' },
69
- true, // extractable - required for JWK export
70
- ['sign', 'verify']
71
- );
72
-
73
- const publicKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey);
74
- const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
75
-
76
- return {
77
- publicKey: publicKeyJwk,
78
- privateKey: privateKeyJwk
79
- };
80
- } catch (err) {
81
- console.warn('[DPoP] WebCrypto API failed, trying Node.js crypto API', err);
82
- }
83
- }
84
-
85
- // Fallback: Node.js crypto API (works on iOS)
86
- return new Promise((resolve, reject) => {
87
- crypto.generateKeyPair('ec', { namedCurve: 'P-256' }, (err: any, publicKey: any, privateKey: any) => {
88
- if (err) return reject(err);
89
- try {
90
- const pJwk = publicKey.export({ format: 'jwk' });
91
- const prJwk = privateKey.export({ format: 'jwk' });
92
- resolve({ publicKey: pJwk, privateKey: prJwk });
93
- } catch (exportErr) {
94
- reject(exportErr);
95
- }
96
- });
97
- });
98
- }
99
-
100
- async signProof(payload: Record<string, any>, keyPair: DPoPKeyPair): Promise<string> {
101
- const crypto = getCrypto();
102
- if (!crypto) {
103
- throw new Error('Crypto module not available for signing');
104
- }
105
-
106
- // 1. Construct Header
107
- const header = {
108
- typ: 'dpop+jwt',
109
- alg: 'ES256',
110
- jwk: keyPair.publicKey
111
- };
112
-
113
- // 2. Add Claims (iat/jti)
114
- const finalPayload = {
115
- ...payload,
116
- iat: payload.iat || Math.floor(Date.now() / 1000),
117
- jti: payload.jti || (crypto.randomUUID?.() || `${Date.now()}-${Math.random()}`)
118
- };
119
-
120
- // 3. Encode
121
- const b64Header = this.base64Url(JSON.stringify(header));
122
- const b64Payload = this.base64Url(JSON.stringify(finalPayload));
123
- const signingInput = `${b64Header}.${b64Payload}`;
124
-
125
- // 4. Sign - try WebCrypto first, fallback to Node.js crypto
126
- if (crypto.subtle) {
127
- try {
128
- const privateKey = await crypto.subtle.importKey(
129
- 'jwk',
130
- keyPair.privateKey,
131
- { name: 'ECDSA', namedCurve: 'P-256' },
132
- false,
133
- ['sign']
134
- );
135
-
136
- const signatureBuffer = await crypto.subtle.sign(
137
- { name: 'ECDSA', hash: 'SHA-256' },
138
- privateKey,
139
- Buffer.from(signingInput)
140
- );
141
-
142
- // WebCrypto returns signature in IEEE P1363 format (r || s), which is what we need for JWT
143
- return `${signingInput}.${this.base64UrlBuffer(Buffer.from(signatureBuffer))}`;
144
- } catch (err) {
145
- console.warn('[DPoP] WebCrypto sign failed, trying Node.js crypto', err);
146
- }
147
- }
148
-
149
- // Fallback: Node.js crypto API
150
- const sign = crypto.createSign('SHA256');
151
- sign.update(signingInput);
152
- const privateKeyObj = crypto.createPrivateKey({ key: keyPair.privateKey as any, format: 'jwk' });
153
- const signature = sign.sign(privateKeyObj);
154
-
155
- return `${signingInput}.${this.base64UrlBuffer(signature)}`;
156
- }
157
-
158
- async hashAccessToken(accessToken: string): Promise<string> {
159
- const crypto = getCrypto();
160
- if (!crypto) {
161
- throw new Error('Crypto module not available for hashing');
162
- }
163
-
164
- // Try WebCrypto first
165
- if (crypto.subtle) {
166
- try {
167
- const hashBuffer = await crypto.subtle.digest('SHA-256', Buffer.from(accessToken));
168
- return this.base64UrlBuffer(Buffer.from(hashBuffer));
169
- } catch (err) {
170
- // Fallback to Node.js crypto
171
- }
172
- }
173
-
174
- const hash = crypto.createHash('sha256').update(accessToken).digest();
175
- return this.base64UrlBuffer(hash);
176
- }
177
-
178
- // --- Helpers ---
179
- private base64Url(str: string): string {
180
- return this.base64UrlBuffer(Buffer.from(str));
181
- }
182
-
183
- private base64UrlBuffer(buf: Buffer | Uint8Array): string {
184
- const buffer = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
185
- return buffer.toString('base64')
186
- .replace(/=/g, '')
187
- .replace(/\+/g, '-')
188
- .replace(/\//g, '_');
189
- }
190
- }
1
+ import { Platform } from 'react-native';
2
+ import { Buffer } from 'buffer';
3
+ import { DPoPCryptoProvider, DPoPKeyPair } from '@explorins/pers-sdk/core';
4
+
5
+ // Lazy-loaded crypto module - initialized on first use to avoid native module timing issues
6
+ let _crypto: any = null;
7
+ let _cryptoInitialized = false;
8
+
9
+ /**
10
+ * Lazily load the crypto module.
11
+ *
12
+ * Supports customer pre-initialization via global.__QuickCrypto for environments
13
+ * where native module timing is unpredictable (e.g., certain React Native setups).
14
+ *
15
+ * @returns The crypto module or null if unavailable
16
+ */
17
+ function getCrypto(): any {
18
+ if (_cryptoInitialized) {
19
+ return _crypto;
20
+ }
21
+
22
+ _cryptoInitialized = true;
23
+
24
+ if (Platform.OS === 'web') {
25
+ // On Web, we shouldn't be using this provider (Core SDK has WebDPoPProvider)
26
+ _crypto = {
27
+ generateKeyPair: () => { throw new Error('ReactNativeDPoPProvider not supported on Web'); },
28
+ randomUUID: () => globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random()}`
29
+ };
30
+ return _crypto;
31
+ }
32
+
33
+ // Check for customer pre-initialized global (for native module timing issues)
34
+ if (typeof global !== 'undefined' && (global as any).__QuickCrypto) {
35
+ _crypto = (global as any).__QuickCrypto;
36
+ return _crypto;
37
+ }
38
+
39
+ // Standard lazy load
40
+ try {
41
+ _crypto = require('react-native-quick-crypto').default || require('react-native-quick-crypto');
42
+ } catch (e) {
43
+ console.warn('ReactNativeDPoPProvider: Failed to load react-native-quick-crypto.', e);
44
+ console.warn('Tip: If you encounter timing issues, pre-initialize in index.js: global.__QuickCrypto = require("react-native-quick-crypto")');
45
+ _crypto = null;
46
+ }
47
+
48
+ return _crypto;
49
+ }
50
+
51
+ export class ReactNativeDPoPProvider implements DPoPCryptoProvider {
52
+ /**
53
+ * Generates a new key pair (ES256 recommended)
54
+ *
55
+ * Uses WebCrypto API (crypto.subtle) for cross-platform compatibility.
56
+ * Falls back to Node.js crypto API on iOS if needed.
57
+ */
58
+ async generateKeyPair(options?: { extractable?: boolean }): Promise<DPoPKeyPair> {
59
+ const crypto = getCrypto();
60
+ if (!crypto) {
61
+ throw new Error('Crypto module not available. Install react-native-quick-crypto or pre-initialize global.__QuickCrypto');
62
+ }
63
+
64
+ // Try WebCrypto API first (works on both iOS and Android)
65
+ if (crypto.subtle) {
66
+ try {
67
+ const keyPair = await crypto.subtle.generateKey(
68
+ { name: 'ECDSA', namedCurve: 'P-256' },
69
+ true, // extractable - required for JWK export
70
+ ['sign', 'verify']
71
+ );
72
+
73
+ const publicKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.publicKey);
74
+ const privateKeyJwk = await crypto.subtle.exportKey('jwk', keyPair.privateKey);
75
+
76
+ return {
77
+ publicKey: publicKeyJwk,
78
+ privateKey: privateKeyJwk
79
+ };
80
+ } catch (err) {
81
+ console.warn('[DPoP] WebCrypto API failed, trying Node.js crypto API', err);
82
+ }
83
+ }
84
+
85
+ // Fallback: Node.js crypto API (works on iOS)
86
+ return new Promise((resolve, reject) => {
87
+ crypto.generateKeyPair('ec', { namedCurve: 'P-256' }, (err: any, publicKey: any, privateKey: any) => {
88
+ if (err) return reject(err);
89
+ try {
90
+ const pJwk = publicKey.export({ format: 'jwk' });
91
+ const prJwk = privateKey.export({ format: 'jwk' });
92
+ resolve({ publicKey: pJwk, privateKey: prJwk });
93
+ } catch (exportErr) {
94
+ reject(exportErr);
95
+ }
96
+ });
97
+ });
98
+ }
99
+
100
+ async signProof(payload: Record<string, any>, keyPair: DPoPKeyPair): Promise<string> {
101
+ const crypto = getCrypto();
102
+ if (!crypto) {
103
+ throw new Error('Crypto module not available for signing');
104
+ }
105
+
106
+ // 1. Construct Header
107
+ const header = {
108
+ typ: 'dpop+jwt',
109
+ alg: 'ES256',
110
+ jwk: keyPair.publicKey
111
+ };
112
+
113
+ // 2. Add Claims (iat/jti)
114
+ const finalPayload = {
115
+ ...payload,
116
+ iat: payload.iat || Math.floor(Date.now() / 1000),
117
+ jti: payload.jti || (crypto.randomUUID?.() || `${Date.now()}-${Math.random()}`)
118
+ };
119
+
120
+ // 3. Encode
121
+ const b64Header = this.base64Url(JSON.stringify(header));
122
+ const b64Payload = this.base64Url(JSON.stringify(finalPayload));
123
+ const signingInput = `${b64Header}.${b64Payload}`;
124
+
125
+ // 4. Sign - try WebCrypto first, fallback to Node.js crypto
126
+ if (crypto.subtle) {
127
+ try {
128
+ const privateKey = await crypto.subtle.importKey(
129
+ 'jwk',
130
+ keyPair.privateKey,
131
+ { name: 'ECDSA', namedCurve: 'P-256' },
132
+ false,
133
+ ['sign']
134
+ );
135
+
136
+ const signatureBuffer = await crypto.subtle.sign(
137
+ { name: 'ECDSA', hash: 'SHA-256' },
138
+ privateKey,
139
+ Buffer.from(signingInput)
140
+ );
141
+
142
+ // WebCrypto returns signature in IEEE P1363 format (r || s), which is what we need for JWT
143
+ return `${signingInput}.${this.base64UrlBuffer(Buffer.from(signatureBuffer))}`;
144
+ } catch (err) {
145
+ console.warn('[DPoP] WebCrypto sign failed, trying Node.js crypto', err);
146
+ }
147
+ }
148
+
149
+ // Fallback: Node.js crypto API
150
+ const sign = crypto.createSign('SHA256');
151
+ sign.update(signingInput);
152
+ const privateKeyObj = crypto.createPrivateKey({ key: keyPair.privateKey as any, format: 'jwk' });
153
+ const signature = sign.sign(privateKeyObj);
154
+
155
+ return `${signingInput}.${this.base64UrlBuffer(signature)}`;
156
+ }
157
+
158
+ async hashAccessToken(accessToken: string): Promise<string> {
159
+ const crypto = getCrypto();
160
+ if (!crypto) {
161
+ throw new Error('Crypto module not available for hashing');
162
+ }
163
+
164
+ // Try WebCrypto first
165
+ if (crypto.subtle) {
166
+ try {
167
+ const hashBuffer = await crypto.subtle.digest('SHA-256', Buffer.from(accessToken));
168
+ return this.base64UrlBuffer(Buffer.from(hashBuffer));
169
+ } catch (err) {
170
+ // Fallback to Node.js crypto
171
+ }
172
+ }
173
+
174
+ const hash = crypto.createHash('sha256').update(accessToken).digest();
175
+ return this.base64UrlBuffer(hash);
176
+ }
177
+
178
+ // --- Helpers ---
179
+ private base64Url(str: string): string {
180
+ return this.base64UrlBuffer(Buffer.from(str));
181
+ }
182
+
183
+ private base64UrlBuffer(buf: Buffer | Uint8Array): string {
184
+ const buffer = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
185
+ return buffer.toString('base64')
186
+ .replace(/=/g, '')
187
+ .replace(/\+/g, '-')
188
+ .replace(/\//g, '_');
189
+ }
190
+ }