@explorins/pers-sdk-react-native 2.3.7 → 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 (58) 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/useWeb3.js +4 -4
  11. package/dist/index.js +2400 -487
  12. package/dist/index.js.map +1 -1
  13. package/dist/providers/PersSDKProvider.d.ts +4 -0
  14. package/dist/providers/PersSDKProvider.d.ts.map +1 -1
  15. package/dist/providers/PersSDKProvider.js +14 -0
  16. package/dist/providers/react-native-http-client.d.ts +2 -0
  17. package/dist/providers/react-native-http-client.d.ts.map +1 -1
  18. package/dist/providers/react-native-http-client.js +5 -2
  19. package/dist/storage/rn-secure-storage.d.ts.map +1 -1
  20. package/dist/storage/rn-secure-storage.js +21 -8
  21. package/package.json +3 -3
  22. package/src/__tests__/PersSDKProvider.test.tsx +484 -420
  23. package/src/__tests__/setup.ts +40 -40
  24. package/src/hooks/index.ts +60 -60
  25. package/src/hooks/useAnalytics.ts +327 -327
  26. package/src/hooks/useAuth.ts +265 -265
  27. package/src/hooks/useBookings.ts +191 -191
  28. package/src/hooks/useBusiness.ts +251 -251
  29. package/src/hooks/useCampaigns.ts +500 -500
  30. package/src/hooks/useDonations.ts +66 -66
  31. package/src/hooks/useEvents.ts +372 -372
  32. package/src/hooks/useFiles.ts +155 -155
  33. package/src/hooks/useIPFSUrl.ts +192 -192
  34. package/src/hooks/usePurchases.ts +65 -65
  35. package/src/hooks/useRedemptions.ts +467 -467
  36. package/src/hooks/useTenants.ts +72 -72
  37. package/src/hooks/useTokenBalances.ts +385 -385
  38. package/src/hooks/useTokens.ts +313 -313
  39. package/src/hooks/useTransactionSigner.ts +611 -611
  40. package/src/hooks/useTransactions.ts +299 -299
  41. package/src/hooks/useTriggerSources.ts +301 -301
  42. package/src/hooks/useUserStatus.ts +61 -61
  43. package/src/hooks/useUsers.ts +167 -167
  44. package/src/hooks/useWeb3.ts +355 -355
  45. package/src/index.ts +777 -777
  46. package/src/polyfills/index.ts +160 -160
  47. package/src/polyfills/web3-polyfills.ts +97 -97
  48. package/src/providers/PersSDKProvider.tsx +393 -374
  49. package/src/providers/react-native-auth-provider.ts +110 -110
  50. package/src/providers/react-native-http-client.ts +150 -145
  51. package/src/providers/rn-dpop-provider.ts +190 -190
  52. package/src/storage/async-storage-token-storage.ts +185 -185
  53. package/src/storage/rn-secure-storage.ts +182 -170
  54. package/src/types/react-native-globals.d.ts +45 -45
  55. package/src/utils/index.ts +8 -8
  56. package/src/utils/platform-detection.ts +86 -86
  57. package/dist/index-CzLxqePZ.js +0 -7717
  58. 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
+ }