@explorins/pers-sdk-react-native 2.2.0-alpha.3 → 2.2.0-alpha.5
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.
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/useRedemptions.d.ts +1 -1
- package/dist/hooks/useTransactionSigner.d.ts +5 -4
- package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.js +18 -8
- package/dist/hooks/useTransactions.d.ts +1 -1
- package/dist/index.js +68 -52
- package/dist/index.js.map +1 -1
- package/dist/storage/async-storage-token-storage.d.ts +13 -1
- package/dist/storage/async-storage-token-storage.d.ts.map +1 -1
- package/dist/storage/async-storage-token-storage.js +40 -30
- package/package.json +2 -2
- package/src/hooks/useTransactionSigner.ts +28 -12
- package/src/storage/async-storage-token-storage.ts +49 -33
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AsyncStorage Token Storage for React Native Mobile Platforms
|
|
3
3
|
*
|
|
4
|
-
* Bundler-agnostic AsyncStorage implementation for mobile platforms
|
|
4
|
+
* Bundler-agnostic AsyncStorage implementation for mobile platforms.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: Due to bundler conflicts between Rollup (SDK) and Metro (app),
|
|
7
|
+
* the consuming app MUST set global.AsyncStorageModule before using this SDK:
|
|
8
|
+
*
|
|
9
|
+
* ```javascript
|
|
10
|
+
* // In your app's index.js, BEFORE importing the SDK:
|
|
11
|
+
* import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
12
|
+
* global.AsyncStorageModule = AsyncStorage;
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
import type { TokenStorage } from '@explorins/pers-sdk/core';
|
|
16
|
+
declare global {
|
|
17
|
+
var AsyncStorageModule: any;
|
|
18
|
+
}
|
|
7
19
|
/**
|
|
8
20
|
* AsyncStorage implementation for mobile platforms
|
|
9
21
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-storage-token-storage.d.ts","sourceRoot":"","sources":["../../src/storage/async-storage-token-storage.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"async-storage-token-storage.d.ts","sourceRoot":"","sources":["../../src/storage/async-storage-token-storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,kBAAkB,EAAE,GAAG,CAAC;CAC7B;AA4FD;;;;;GAKG;AACH,qBAAa,wBAAyB,YAAW,YAAY;IAC3D,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,YAAY,CAA8B;gBAEtC,SAAS,GAAE,MAAuB;IAgBxC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW9C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAYxC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB7B"}
|
|
@@ -1,52 +1,62 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AsyncStorage Token Storage for React Native Mobile Platforms
|
|
3
3
|
*
|
|
4
|
-
* Bundler-agnostic AsyncStorage implementation for mobile platforms
|
|
4
|
+
* Bundler-agnostic AsyncStorage implementation for mobile platforms.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: Due to bundler conflicts between Rollup (SDK) and Metro (app),
|
|
7
|
+
* the consuming app MUST set global.AsyncStorageModule before using this SDK:
|
|
8
|
+
*
|
|
9
|
+
* ```javascript
|
|
10
|
+
* // In your app's index.js, BEFORE importing the SDK:
|
|
11
|
+
* import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
12
|
+
* global.AsyncStorageModule = AsyncStorage;
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* When the SDK is pre-bundled (e.g., with Rollup) and then consumed by an app
|
|
10
|
-
* that uses Metro, the static import can get resolved incorrectly due to module
|
|
11
|
-
* hoisting and namespace collisions.
|
|
16
|
+
* Get AsyncStorage from the global that the app must set.
|
|
12
17
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
18
|
+
* This bypasses all bundler resolution issues by having the app
|
|
19
|
+
* explicitly provide the AsyncStorage module via a global variable.
|
|
15
20
|
*/
|
|
16
21
|
function getAsyncStorage() {
|
|
17
|
-
//
|
|
18
|
-
|
|
22
|
+
// Check if the app has set the global
|
|
23
|
+
if (global.AsyncStorageModule) {
|
|
24
|
+
const module = global.AsyncStorageModule;
|
|
25
|
+
// Validate it has the expected methods
|
|
26
|
+
if (typeof module?.getItem === 'function') {
|
|
27
|
+
console.log('[AsyncStorage] Using global.AsyncStorageModule (direct)');
|
|
28
|
+
return module;
|
|
29
|
+
}
|
|
30
|
+
else if (typeof module?.default?.getItem === 'function') {
|
|
31
|
+
console.log('[AsyncStorage] Using global.AsyncStorageModule.default');
|
|
32
|
+
return module.default;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
// Fallback: try require (may not work due to bundler conflicts)
|
|
19
36
|
try {
|
|
20
|
-
//
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
21
38
|
const module = require('@react-native-async-storage/async-storage');
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const hasDefaultGetItem = typeof module?.default?.getItem === 'function';
|
|
25
|
-
console.log('[AsyncStorage] Module resolution:', {
|
|
26
|
-
hasGetItem,
|
|
27
|
-
hasDefaultGetItem,
|
|
28
|
-
moduleType: typeof module,
|
|
29
|
-
keys: module ? Object.keys(module).slice(0, 10) : []
|
|
30
|
-
});
|
|
31
|
-
if (hasDefaultGetItem) {
|
|
39
|
+
if (typeof module?.default?.getItem === 'function') {
|
|
40
|
+
console.log('[AsyncStorage] Fallback: using require().default');
|
|
32
41
|
return module.default;
|
|
33
42
|
}
|
|
34
|
-
else if (
|
|
43
|
+
else if (typeof module?.getItem === 'function') {
|
|
44
|
+
console.log('[AsyncStorage] Fallback: using require() direct');
|
|
35
45
|
return module;
|
|
36
46
|
}
|
|
37
|
-
else {
|
|
38
|
-
throw new Error('AsyncStorage module found but missing getItem method');
|
|
39
|
-
}
|
|
40
47
|
}
|
|
41
|
-
catch (
|
|
42
|
-
|
|
43
|
-
throw new Error('Failed to load @react-native-async-storage/async-storage. ' +
|
|
44
|
-
'Make sure it is installed and properly linked.');
|
|
48
|
+
catch (e) {
|
|
49
|
+
// Ignore require errors
|
|
45
50
|
}
|
|
51
|
+
// If we get here, provide a helpful error
|
|
52
|
+
throw new Error('AsyncStorage not available. Please add this to your app\'s index.js BEFORE importing the SDK:\n\n' +
|
|
53
|
+
' import AsyncStorage from \'@react-native-async-storage/async-storage\';\n' +
|
|
54
|
+
' global.AsyncStorageModule = AsyncStorage;\n\n' +
|
|
55
|
+
'This is required due to bundler conflicts between Rollup and Metro.');
|
|
46
56
|
}
|
|
47
57
|
/**
|
|
48
58
|
* Bundler-agnostic AsyncStorage wrapper
|
|
49
|
-
*
|
|
59
|
+
* Uses global injection to avoid bundler conflicts
|
|
50
60
|
*/
|
|
51
61
|
class BundlerAgnosticAsyncStorage {
|
|
52
62
|
constructor() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@explorins/pers-sdk-react-native",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.5",
|
|
4
4
|
"description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@explorins/pers-sdk": "^2.1.32",
|
|
41
|
-
"@explorins/pers-signer": "^1.0.
|
|
41
|
+
"@explorins/pers-signer": "^1.0.34",
|
|
42
42
|
"buffer": "^6.0.3",
|
|
43
43
|
"ethers": "^6.15.0"
|
|
44
44
|
},
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { useCallback, useState, useRef, useEffect } from 'react';
|
|
2
2
|
// import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// TYPE-ONLY imports from /types entry - NO native module deps, safe at any time
|
|
5
|
+
import type { PersSignerConfig, StatusCallback, StatusUpdateData } from '@explorins/pers-signer/types';
|
|
6
|
+
import type { SigningStatus as SigningStatusType } from '@explorins/pers-signer/types';
|
|
7
|
+
// Runtime const import - also from /types (no native deps)
|
|
8
|
+
import { SigningStatus as SigningStatusConst } from '@explorins/pers-signer/types';
|
|
4
9
|
|
|
5
10
|
// Import actual SDK types from the React Native-specific export
|
|
6
11
|
type PersSignerSDK = import('@explorins/pers-signer/react-native').PersSignerSDK;
|
|
@@ -8,21 +13,29 @@ type SubmissionResult = import('@explorins/pers-signer/react-native').Submission
|
|
|
8
13
|
type AuthenticatedUser = import('@explorins/pers-signer/react-native').AuthenticatedUser;
|
|
9
14
|
type TransactionSigningResult = import('@explorins/pers-signer/react-native').TransactionSigningResult;
|
|
10
15
|
|
|
11
|
-
// Re-export
|
|
12
|
-
export { SigningStatus };
|
|
16
|
+
// Re-export the type for external consumers
|
|
17
|
+
export type { SigningStatusType as SigningStatus };
|
|
13
18
|
export type { StatusUpdateData };
|
|
14
19
|
|
|
15
20
|
/**
|
|
16
21
|
* Simple status callback function type for React Native consumers
|
|
17
22
|
* (Simplified from the signer SDK's object-based StatusCallback interface)
|
|
18
23
|
*/
|
|
19
|
-
export type OnStatusUpdateFn = (status:
|
|
24
|
+
export type OnStatusUpdateFn = (status: SigningStatusType, message: string, data?: StatusUpdateData) => void;
|
|
20
25
|
|
|
21
26
|
|
|
22
|
-
// Lazy-loaded signer SDK
|
|
27
|
+
// Lazy-loaded signer SDK - initialized on first use to avoid native module timing issues
|
|
23
28
|
let _createPersSignerSDK: ((config: PersSignerConfig) => Promise<PersSignerSDK>) | null = null;
|
|
24
29
|
let _signerInitAttempted = false;
|
|
25
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Get the SigningStatus const object
|
|
33
|
+
* Now directly imported from /types (no native deps, always available)
|
|
34
|
+
*/
|
|
35
|
+
function getSigningStatus(): typeof SigningStatusType {
|
|
36
|
+
return SigningStatusConst;
|
|
37
|
+
}
|
|
38
|
+
|
|
26
39
|
/**
|
|
27
40
|
* Lazily load the PERS Signer SDK.
|
|
28
41
|
*
|
|
@@ -41,7 +54,8 @@ function getSignerSDKFactory(): ((config: PersSignerConfig) => Promise<PersSigne
|
|
|
41
54
|
|
|
42
55
|
// Check for customer pre-initialized global (for native module timing issues)
|
|
43
56
|
if (typeof global !== 'undefined' && (global as any).__PersSigner?.createPersSignerSDK) {
|
|
44
|
-
|
|
57
|
+
const globalModule = (global as any).__PersSigner;
|
|
58
|
+
_createPersSignerSDK = globalModule.createPersSignerSDK;
|
|
45
59
|
return _createPersSignerSDK;
|
|
46
60
|
}
|
|
47
61
|
|
|
@@ -79,7 +93,7 @@ export interface TransactionSignerHook {
|
|
|
79
93
|
signPersTransaction: (jwt: string, onStatusUpdate?: OnStatusUpdateFn) => Promise<TransactionSigningResult>;
|
|
80
94
|
isSignerInitialized: boolean;
|
|
81
95
|
isSignerAvailable: boolean;
|
|
82
|
-
currentStatus:
|
|
96
|
+
currentStatus: SigningStatusType | null;
|
|
83
97
|
statusMessage: string | null;
|
|
84
98
|
}
|
|
85
99
|
|
|
@@ -266,7 +280,7 @@ const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0
|
|
|
266
280
|
export const useTransactionSigner = (): TransactionSignerHook => {
|
|
267
281
|
// const { isInitialized, isAuthenticated, user } = usePersSDK();
|
|
268
282
|
const [isSignerInitialized, setIsSignerInitialized] = useState(false);
|
|
269
|
-
const [currentStatus, setCurrentStatus] = useState<
|
|
283
|
+
const [currentStatus, setCurrentStatus] = useState<SigningStatusType | null>(null);
|
|
270
284
|
const [statusMessage, setStatusMessage] = useState<string | null>(null);
|
|
271
285
|
const signerSDKRef = useRef<PersSignerSDK | null>(null);
|
|
272
286
|
|
|
@@ -398,7 +412,7 @@ export const useTransactionSigner = (): TransactionSignerHook => {
|
|
|
398
412
|
|
|
399
413
|
// Create status callback wrapper that updates both hook state and calls user callback
|
|
400
414
|
const statusCallback: StatusCallback = {
|
|
401
|
-
onStatusUpdate: (status:
|
|
415
|
+
onStatusUpdate: (status: SigningStatusType, message: string, data?: StatusUpdateData) => {
|
|
402
416
|
setCurrentStatus(status);
|
|
403
417
|
setStatusMessage(message);
|
|
404
418
|
onStatusUpdate?.(status, message, data);
|
|
@@ -413,7 +427,8 @@ export const useTransactionSigner = (): TransactionSignerHook => {
|
|
|
413
427
|
|
|
414
428
|
} catch (error) {
|
|
415
429
|
console.error('[useTransactionSigner] JWT transaction signing failed:', error);
|
|
416
|
-
|
|
430
|
+
const SigningStatusEnum = getSigningStatus();
|
|
431
|
+
if (SigningStatusEnum) setCurrentStatus(SigningStatusEnum.ERROR);
|
|
417
432
|
setStatusMessage(error instanceof Error ? error.message : 'Transaction failed');
|
|
418
433
|
throw error; // Re-throw to maintain error handling upstream
|
|
419
434
|
}
|
|
@@ -459,7 +474,7 @@ export const useTransactionSigner = (): TransactionSignerHook => {
|
|
|
459
474
|
|
|
460
475
|
// Create status callback wrapper
|
|
461
476
|
const statusCallback: StatusCallback = {
|
|
462
|
-
onStatusUpdate: (status:
|
|
477
|
+
onStatusUpdate: (status: SigningStatusType, message: string, data?: StatusUpdateData) => {
|
|
463
478
|
setCurrentStatus(status);
|
|
464
479
|
setStatusMessage(message);
|
|
465
480
|
onStatusUpdate?.(status, message, data);
|
|
@@ -472,7 +487,8 @@ export const useTransactionSigner = (): TransactionSignerHook => {
|
|
|
472
487
|
return signingResult;
|
|
473
488
|
} catch (error) {
|
|
474
489
|
console.error('[useTransactionSigner] Sign-only transaction failed:', error);
|
|
475
|
-
|
|
490
|
+
const SigningStatusEnum = getSigningStatus();
|
|
491
|
+
if (SigningStatusEnum) setCurrentStatus(SigningStatusEnum.ERROR);
|
|
476
492
|
setStatusMessage(error instanceof Error ? error.message : 'Signing failed');
|
|
477
493
|
throw error;
|
|
478
494
|
}
|
|
@@ -1,58 +1,74 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AsyncStorage Token Storage for React Native Mobile Platforms
|
|
3
3
|
*
|
|
4
|
-
* Bundler-agnostic AsyncStorage implementation for mobile platforms
|
|
4
|
+
* Bundler-agnostic AsyncStorage implementation for mobile platforms.
|
|
5
|
+
*
|
|
6
|
+
* IMPORTANT: Due to bundler conflicts between Rollup (SDK) and Metro (app),
|
|
7
|
+
* the consuming app MUST set global.AsyncStorageModule before using this SDK:
|
|
8
|
+
*
|
|
9
|
+
* ```javascript
|
|
10
|
+
* // In your app's index.js, BEFORE importing the SDK:
|
|
11
|
+
* import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
12
|
+
* global.AsyncStorageModule = AsyncStorage;
|
|
13
|
+
* ```
|
|
5
14
|
*/
|
|
6
15
|
|
|
7
16
|
import type { TokenStorage } from '@explorins/pers-sdk/core';
|
|
8
17
|
|
|
18
|
+
// Declare global type for TypeScript
|
|
19
|
+
declare global {
|
|
20
|
+
var AsyncStorageModule: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
9
23
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* When the SDK is pre-bundled (e.g., with Rollup) and then consumed by an app
|
|
13
|
-
* that uses Metro, the static import can get resolved incorrectly due to module
|
|
14
|
-
* hoisting and namespace collisions.
|
|
24
|
+
* Get AsyncStorage from the global that the app must set.
|
|
15
25
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
26
|
+
* This bypasses all bundler resolution issues by having the app
|
|
27
|
+
* explicitly provide the AsyncStorage module via a global variable.
|
|
18
28
|
*/
|
|
19
29
|
function getAsyncStorage(): any {
|
|
20
|
-
//
|
|
21
|
-
|
|
30
|
+
// Check if the app has set the global
|
|
31
|
+
if (global.AsyncStorageModule) {
|
|
32
|
+
const module = global.AsyncStorageModule;
|
|
33
|
+
|
|
34
|
+
// Validate it has the expected methods
|
|
35
|
+
if (typeof module?.getItem === 'function') {
|
|
36
|
+
console.log('[AsyncStorage] Using global.AsyncStorageModule (direct)');
|
|
37
|
+
return module;
|
|
38
|
+
} else if (typeof module?.default?.getItem === 'function') {
|
|
39
|
+
console.log('[AsyncStorage] Using global.AsyncStorageModule.default');
|
|
40
|
+
return module.default;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Fallback: try require (may not work due to bundler conflicts)
|
|
22
45
|
try {
|
|
23
|
-
//
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
24
47
|
const module = require('@react-native-async-storage/async-storage');
|
|
25
48
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const hasDefaultGetItem = typeof module?.default?.getItem === 'function';
|
|
29
|
-
|
|
30
|
-
console.log('[AsyncStorage] Module resolution:', {
|
|
31
|
-
hasGetItem,
|
|
32
|
-
hasDefaultGetItem,
|
|
33
|
-
moduleType: typeof module,
|
|
34
|
-
keys: module ? Object.keys(module).slice(0, 10) : []
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
if (hasDefaultGetItem) {
|
|
49
|
+
if (typeof module?.default?.getItem === 'function') {
|
|
50
|
+
console.log('[AsyncStorage] Fallback: using require().default');
|
|
38
51
|
return module.default;
|
|
39
|
-
} else if (
|
|
52
|
+
} else if (typeof module?.getItem === 'function') {
|
|
53
|
+
console.log('[AsyncStorage] Fallback: using require() direct');
|
|
40
54
|
return module;
|
|
41
|
-
} else {
|
|
42
|
-
throw new Error('AsyncStorage module found but missing getItem method');
|
|
43
55
|
}
|
|
44
|
-
} catch (
|
|
45
|
-
|
|
46
|
-
throw new Error(
|
|
47
|
-
'Failed to load @react-native-async-storage/async-storage. ' +
|
|
48
|
-
'Make sure it is installed and properly linked.'
|
|
49
|
-
);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
// Ignore require errors
|
|
50
58
|
}
|
|
59
|
+
|
|
60
|
+
// If we get here, provide a helpful error
|
|
61
|
+
throw new Error(
|
|
62
|
+
'AsyncStorage not available. Please add this to your app\'s index.js BEFORE importing the SDK:\n\n' +
|
|
63
|
+
' import AsyncStorage from \'@react-native-async-storage/async-storage\';\n' +
|
|
64
|
+
' global.AsyncStorageModule = AsyncStorage;\n\n' +
|
|
65
|
+
'This is required due to bundler conflicts between Rollup and Metro.'
|
|
66
|
+
);
|
|
51
67
|
}
|
|
52
68
|
|
|
53
69
|
/**
|
|
54
70
|
* Bundler-agnostic AsyncStorage wrapper
|
|
55
|
-
*
|
|
71
|
+
* Uses global injection to avoid bundler conflicts
|
|
56
72
|
*/
|
|
57
73
|
class BundlerAgnosticAsyncStorage {
|
|
58
74
|
private storage: any;
|