@explorins/pers-sdk-react-native 1.5.18 → 1.5.21

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 (49) hide show
  1. package/README.md +336 -234
  2. package/dist/hooks/index.d.ts +1 -1
  3. package/dist/hooks/index.d.ts.map +1 -1
  4. package/dist/hooks/useAnalytics.d.ts +6 -2
  5. package/dist/hooks/useAnalytics.d.ts.map +1 -1
  6. package/dist/hooks/useAuth.d.ts +1 -1
  7. package/dist/hooks/useAuth.d.ts.map +1 -1
  8. package/dist/hooks/useAuth.js +7 -7
  9. package/dist/hooks/useRedemptions.d.ts.map +1 -1
  10. package/dist/hooks/useRedemptions.js +4 -4
  11. package/dist/hooks/useTenants.d.ts.map +1 -1
  12. package/dist/hooks/useTenants.js +0 -1
  13. package/dist/hooks/useTransactionSigner.d.ts +186 -53
  14. package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
  15. package/dist/hooks/useTransactionSigner.js +285 -102
  16. package/dist/hooks/useTransactions.d.ts +2 -2
  17. package/dist/hooks/useTransactions.d.ts.map +1 -1
  18. package/dist/hooks/useTransactions.js +9 -10
  19. package/dist/hooks/useWeb3.d.ts +8 -2
  20. package/dist/hooks/useWeb3.d.ts.map +1 -1
  21. package/dist/index.d.ts +211 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +21061 -18475
  24. package/dist/index.js.map +1 -1
  25. package/dist/providers/PersSDKProvider.d.ts +2 -8
  26. package/dist/providers/PersSDKProvider.d.ts.map +1 -1
  27. package/dist/providers/PersSDKProvider.js +16 -31
  28. package/dist/providers/react-native-auth-provider.d.ts +24 -36
  29. package/dist/providers/react-native-auth-provider.d.ts.map +1 -1
  30. package/dist/providers/react-native-auth-provider.js +35 -146
  31. package/dist/providers/react-native-http-client.d.ts +15 -0
  32. package/dist/providers/react-native-http-client.d.ts.map +1 -1
  33. package/dist/storage/async-storage-token-storage.d.ts +22 -0
  34. package/dist/storage/async-storage-token-storage.d.ts.map +1 -0
  35. package/dist/storage/async-storage-token-storage.js +113 -0
  36. package/package.json +16 -11
  37. package/src/hooks/index.ts +1 -1
  38. package/src/hooks/useAnalytics.ts +6 -2
  39. package/src/hooks/useAuth.ts +7 -7
  40. package/src/hooks/useRedemptions.ts +5 -7
  41. package/src/hooks/useTenants.ts +0 -1
  42. package/src/hooks/useTransactionSigner.ts +322 -166
  43. package/src/hooks/useTransactions.ts +12 -11
  44. package/src/hooks/useWeb3.ts +8 -1
  45. package/src/index.ts +243 -7
  46. package/src/providers/PersSDKProvider.tsx +21 -40
  47. package/src/providers/react-native-auth-provider.ts +58 -176
  48. package/src/providers/react-native-http-client.ts +15 -0
  49. package/src/storage/async-storage-token-storage.ts +133 -0
@@ -1,53 +1,40 @@
1
1
  import { useCallback, useState, useRef, useEffect } from 'react';
2
- import { usePersSDK } from '../providers/PersSDKProvider';
2
+ // import { usePersSDK } from '../providers/PersSDKProvider';
3
+ import { PersSignerConfig } from '@explorins/pers-signer';
4
+
5
+ // Import actual SDK types from the React Native-specific export
6
+ type PersSignerSDK = import('@explorins/pers-signer/react-native').PersSignerSDK;
7
+ type SubmissionResult = import('@explorins/pers-signer/react-native').SubmissionResult;
8
+ type AuthenticatedUser = import('@explorins/pers-signer/react-native').AuthenticatedUser;
9
+ type TransactionSigningResult = import('@explorins/pers-signer/react-native').TransactionSigningResult;
10
+
3
11
 
4
12
  // Dynamic import the signer SDK to avoid build issues with static dependencies
5
- let createPersSignerSDK: ((config: PersSignerConfig) => Promise<PersSignerSDKInstance>) | null = null;
13
+ let createPersSignerSDK: ((config: PersSignerConfig) => Promise<PersSignerSDK>) | null = null;
6
14
  try {
7
15
  const signerModule = require('@explorins/pers-signer/react-native');
8
16
  createPersSignerSDK = signerModule.createPersSignerSDK;
9
- console.log('[useTransactionSigner] PERS Signer SDK loaded successfully');
10
17
  } catch (error: unknown) {
11
18
  console.warn('[useTransactionSigner] PERS Signer SDK not available:', (error as Error).message);
12
19
  console.warn('[useTransactionSigner] Real blockchain signing will not be available');
13
20
  }
14
21
 
15
- // Simplified configuration matching web frontend
16
- interface PersSignerConfig {
17
- ethersProviderUrl?: string; // Custom blockchain provider
18
- }
19
-
20
- // Simplified SDK interface matching web frontend
21
- interface PersSignerSDKInstance {
22
- authenticateWithJWT: (searchParams: URLSearchParams) => Promise<AuthenticationResult | null>;
23
- authenticateUser: (identifier: string) => Promise<SignerAuthenticatedUser>;
24
- signPersTransaction: (user: SignerAuthenticatedUser, transactionId: string) => Promise<SigningResult>;
25
- }
26
-
27
- // Types matching web frontend
28
- interface AuthenticationResult {
29
- user: SignerAuthenticatedUser;
30
- isExpired: boolean;
31
- }
32
22
 
33
- interface SignerAuthenticatedUser {
34
- identifier: string;
35
- signerAuthToken: string;
36
- persAccessToken: string;
37
- }
38
-
39
- interface SigningResult {
40
- success: boolean;
41
- transactionHash?: string;
42
- error?: string;
43
- }
44
-
45
- // Define our own result type that's compatible with both SDK and our usage
46
- interface TransactionSigningResult {
47
- success: boolean;
48
- transactionHash?: string;
49
- signature?: string;
50
- error?: string;
23
+ /**
24
+ * Return interface for the useTransactionSigner hook
25
+ *
26
+ * Provides secure transaction signing capabilities for EVM blockchain interactions
27
+ * and error handling for React Native applications.
28
+ *
29
+ * @interface TransactionSignerHook
30
+ * @property {Function} signAndSubmitTransactionWithJWT - Main method to sign and submit transactions
31
+ * @property {boolean} isSignerInitialized - Whether the signer SDK has been initialized
32
+ * @property {boolean} isSignerAvailable - Whether signing functionality is fully available
33
+ */
34
+ export interface TransactionSignerHook {
35
+ signAndSubmitTransactionWithJWT: (jwt: string) => Promise<SubmissionResult>;
36
+ isSignerInitialized: boolean;
37
+ isSignerAvailable: boolean;
51
38
  }
52
39
 
53
40
  // Constants - TODO: Move to environment config later
@@ -56,42 +43,187 @@ const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0
56
43
  /**
57
44
  * React Native hook for blockchain transaction signing using PERS Signer SDK
58
45
  *
59
- * Simplified interface matching web frontend - uses high-level SDK methods
60
- * that handle all complexity internally (tenant setup, project keys, etc.).
46
+ * This hook provides a complete blockchain transaction signing solution for React Native
47
+ * applications, integrating with the PERS ecosystem for tourism loyalty and reward systems.
48
+ * It automatically handles WebAuthn authentication, transaction preparation, signing, and
49
+ * blockchain submission in a single convenient interface.
50
+ *
51
+ * **Features:**
52
+ * - Automatic WebAuthn provider initialization for React Native
53
+ * - 5-minute authentication caching to reduce repeated logins
54
+ * - Complete transaction lifecycle management (sign + submit)
55
+ * - Comprehensive error handling with detailed error messages
56
+ * - Real-time status monitoring for UI feedback
57
+ * - Automatic retry logic for network failures
58
+ *
59
+ * **Underlying SDK Methods:**
60
+ * The hook uses the PERS Signer SDK which provides 5 core methods:
61
+ * 1. `loginUser(jwtToken)` - Authenticate user with 5-minute caching
62
+ * 2. `signTransaction(signingData, jwtToken)` - Sign transactions with auto-login
63
+ * 3. `submitTransaction(signingResult, jwtToken)` - Submit signed transactions
64
+ * 4. `signPersTransaction(jwtToken)` - Legacy one-liner for backward compatibility
65
+ * 5. `signAndSubmitPersTransaction(jwtToken)` - Complete sign + submit flow (used by this hook)
66
+ *
67
+ * **Security:**
68
+ * - WebAuthn-based secure authentication (no passwords stored)
69
+ * - JWT token validation and expiration checking
70
+ * - Secure transaction signing using device biometrics/PIN
71
+ * - No sensitive data stored locally
72
+ *
73
+ * @returns {TransactionSignerHook} Hook interface with signing methods and status
61
74
  *
62
75
  * @example
76
+ * **Basic Usage:**
63
77
  * ```typescript
64
- * function TransactionComponent() {
65
- * const { signTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
78
+ * import { useTransactionSigner } from '@explorins/pers-sdk-react-native';
79
+ *
80
+ * function TransactionScreen() {
81
+ * const {
82
+ * signAndSubmitTransactionWithJWT,
83
+ * isSignerAvailable,
84
+ * isSignerInitialized
85
+ * } = useTransactionSigner();
66
86
  *
67
87
  * const handleSign = async (jwtFromRedemption: string) => {
88
+ * if (!isSignerAvailable) {
89
+ * console.error('Signer not available');
90
+ * return;
91
+ * }
92
+ *
68
93
  * try {
69
- * const result = await signTransactionWithJWT(jwtFromRedemption);
94
+ * const result = await signAndSubmitTransactionWithJWT(jwtFromRedemption);
70
95
  * if (result.success) {
71
- * console.log('Transaction signed:', result.transactionHash);
96
+ * console.log('Transaction completed:', result.transactionHash);
97
+ * // Handle successful transaction
98
+ * if (result.shouldRedirect && result.redirectUrl) {
99
+ * // Navigate to success page or external URL
100
+ * }
72
101
  * }
73
102
  * } catch (error) {
74
- * console.error('Signing failed:', error);
103
+ * console.error('Transaction failed:', error.message);
104
+ * // Handle error (show user-friendly message)
75
105
  * }
76
106
  * };
77
107
  *
78
108
  * return (
79
- * <button onClick={handleSign} disabled={!isSignerAvailable}>
80
- * Sign Transaction
81
- * </button>
109
+ * <View style={styles.container}>
110
+ * <TouchableOpacity
111
+ * onPress={() => handleSign(redeemJWT)}
112
+ * disabled={!isSignerAvailable}
113
+ * style={[styles.button, !isSignerAvailable && styles.disabled]}
114
+ * >
115
+ * <Text style={styles.buttonText}>
116
+ * {isSignerInitialized ? 'Sign Transaction' : 'Initializing...'}
117
+ * </Text>
118
+ * </TouchableOpacity>
119
+ * </View>
82
120
  * );
83
121
  * }
84
122
  * ```
123
+ *
124
+ * @example
125
+ * **Advanced Usage with Error Handling:**
126
+ * ```typescript
127
+ * function AdvancedTransactionComponent() {
128
+ * const [isLoading, setIsLoading] = useState(false);
129
+ * const [error, setError] = useState<string | null>(null);
130
+ * const { signAndSubmitTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
131
+ *
132
+ * const handleTransaction = async (jwt: string) => {
133
+ * setIsLoading(true);
134
+ * setError(null);
135
+ *
136
+ * try {
137
+ * const result = await signAndSubmitTransactionWithJWT(jwt);
138
+ *
139
+ * if (result.success) {
140
+ * // Success handling
141
+ * Alert.alert(
142
+ * 'Success',
143
+ * `Transaction completed!\nHash: ${result.transactionHash}`
144
+ * );
145
+ * } else {
146
+ * throw new Error(result.error || 'Transaction failed');
147
+ * }
148
+ * } catch (err) {
149
+ * const errorMessage = err instanceof Error ? err.message : 'Unknown error';
150
+ * setError(errorMessage);
151
+ *
152
+ * // Different error handling based on error type
153
+ * if (errorMessage.includes('expired')) {
154
+ * Alert.alert('Session Expired', 'Please log in again');
155
+ * } else if (errorMessage.includes('network')) {
156
+ * Alert.alert('Network Error', 'Please check your connection');
157
+ * } else {
158
+ * Alert.alert('Transaction Failed', errorMessage);
159
+ * }
160
+ * } finally {
161
+ * setIsLoading(false);
162
+ * }
163
+ * };
164
+ *
165
+ * return (
166
+ * <View>
167
+ * {error && (
168
+ * <Text style={styles.errorText}>{error}</Text>
169
+ * )}
170
+ * <TouchableOpacity
171
+ * onPress={() => handleTransaction(jwtToken)}
172
+ * disabled={!isSignerAvailable || isLoading}
173
+ * >
174
+ * <Text>
175
+ * {isLoading ? 'Processing...' : 'Sign & Submit Transaction'}
176
+ * </Text>
177
+ * </TouchableOpacity>
178
+ * </View>
179
+ * );
180
+ * }
181
+ * ```
182
+ *
183
+ * @example
184
+ * **Integration with PERS SDK:**
185
+ * ```typescript
186
+ * import { usePersSDK } from '@explorins/pers-sdk-react-native';
187
+ * import { useTransactionSigner } from '@explorins/pers-sdk-react-native';
188
+ *
189
+ * function RedemptionFlow() {
190
+ * const { user, redeemTokens } = usePersSDK();
191
+ * const { signAndSubmitTransactionWithJWT } = useTransactionSigner();
192
+ *
193
+ * const handleRedemption = async (tokenAmount: number) => {
194
+ * try {
195
+ * // Step 1: Create redemption with PERS SDK
196
+ * const redemption = await redeemTokens({
197
+ * tokenAmount,
198
+ * destinationAddress: user?.walletAddress
199
+ * });
200
+ *
201
+ * // Step 2: Sign and submit transaction
202
+ * const txResult = await signAndSubmitTransactionWithJWT(redemption.jwtToken);
203
+ *
204
+ * if (txResult.success) {
205
+ * console.log('Redemption completed:', txResult.transactionHash);
206
+ * }
207
+ * } catch (error) {
208
+ * console.error('Redemption failed:', error);
209
+ * }
210
+ * };
211
+ * }
212
+ * ```
213
+ *
214
+ * @see {@link SubmissionResult} for transaction result structure
215
+ * @see {@link TransactionSigningResult} for signing result details
216
+ * @see {@link AuthenticatedUser} for user authentication data
217
+ *
218
+ * @since 1.5.0
85
219
  */
86
- export const useTransactionSigner = () => {
87
- const { isInitialized, isAuthenticated, user } = usePersSDK();
220
+ export const useTransactionSigner = (): TransactionSignerHook => {
221
+ // const { isInitialized, isAuthenticated, user } = usePersSDK();
88
222
  const [isSignerInitialized, setIsSignerInitialized] = useState(false);
89
- const signerSDKRef = useRef<PersSignerSDKInstance | null>(null);
223
+ const signerSDKRef = useRef<PersSignerSDK | null>(null);
90
224
 
91
225
  // Auto-initialize signer SDK when PERS SDK is ready
92
226
  useEffect(() => {
93
- console.log('[useTransactionSigner] Auto-initializing signer SDK...');
94
-
95
227
  const initializeSignerSDK = async () => {
96
228
  if (!createPersSignerSDK) {
97
229
  console.warn('[useTransactionSigner] Signer SDK not available');
@@ -99,14 +231,14 @@ export const useTransactionSigner = () => {
99
231
  }
100
232
 
101
233
  try {
102
- console.log('[useTransactionSigner] Creating PERS Signer SDK...');
234
+ // React Native createPersSignerSDK automatically includes WebAuthn provider
103
235
  const signerSDK = await createPersSignerSDK({
104
- ethersProviderUrl: DEFAULT_ETHERS_PROVIDER
236
+ ethersProviderUrl: DEFAULT_ETHERS_PROVIDER,
237
+ relyingPartyName: 'PERS React Native App'
105
238
  });
106
239
 
107
240
  signerSDKRef.current = signerSDK;
108
241
  setIsSignerInitialized(true);
109
- console.log('[useTransactionSigner] PERS Signer SDK initialized successfully');
110
242
 
111
243
  } catch (error) {
112
244
  console.error('[useTransactionSigner] Failed to initialize signer SDK:', error);
@@ -119,17 +251,85 @@ export const useTransactionSigner = () => {
119
251
  }, [isSignerInitialized]);
120
252
 
121
253
  /**
122
- * Sign a blockchain transaction using JWT token (matching web frontend pattern)
254
+ * Sign and submit a blockchain transaction using JWT token
255
+ *
256
+ * This is the main method for executing blockchain transactions in React Native.
257
+ * It handles the complete transaction lifecycle: authentication, signing, and
258
+ * blockchain submission in a single call.
259
+ *
260
+ * **Process Flow:**
261
+ * 1. Validates the JWT token and extracts transaction data
262
+ * 2. Authenticates the user using WebAuthn (cached for 5 minutes)
263
+ * 3. Fetches transaction data from PERS backend
264
+ * 4. Signs the transaction using device security (biometrics/PIN)
265
+ * 5. Submits the signed transaction to the blockchain
266
+ * 6. Returns detailed result with transaction hash and status
267
+ *
268
+ * **Security Features:**
269
+ * - JWT token validation and expiration checking
270
+ * - WebAuthn authentication with device biometrics
271
+ * - Secure transaction signing without exposing private keys
272
+ * - Automatic session management with secure caching
273
+ *
274
+ * @param {string} jwt - JWT token containing transaction ID and user information
275
+ * Must include: `transactionId`, `identifierEmail`, `tenantId`
276
+ * @returns {Promise<SubmissionResult>} Complete transaction result
277
+ *
278
+ * @throws {Error} 'Transaction signer not initialized' - Hook not ready
279
+ * @throws {Error} 'PERS Signer SDK not available' - SDK installation issue
280
+ * @throws {Error} 'Invalid or expired JWT token' - Token validation failed
281
+ * @throws {Error} 'Authentication failed' - WebAuthn authentication failed
282
+ * @throws {Error} 'Transaction signing failed' - Signing process failed
283
+ * @throws {Error} 'Transaction submission failed' - Blockchain submission failed
123
284
  *
124
- * This method replicates the web frontend flow:
125
- * 1. Extract transaction info from JWT
126
- * 2. Authenticate user with WebAuthn
127
- * 3. Sign transaction with authenticated user
285
+ * @example
286
+ * **Basic Transaction:**
287
+ * ```typescript
288
+ * const { signAndSubmitTransactionWithJWT } = useTransactionSigner();
128
289
  *
129
- * @param jwt - JWT token from redemption flow containing transaction ID
130
- * @returns Promise resolving to signing result with transaction hash
290
+ * const result = await signAndSubmitTransactionWithJWT(jwtToken);
291
+ * if (result.success) {
292
+ * console.log('Transaction Hash:', result.transactionHash);
293
+ * console.log('Blockchain explorer: [Chain-specific explorer URL]');
294
+ * }
295
+ * ```
296
+ *
297
+ * @example
298
+ * **With Error Handling:**
299
+ * ```typescript
300
+ * try {
301
+ * const result = await signAndSubmitTransactionWithJWT(redeemJWT);
302
+ *
303
+ * if (result.success) {
304
+ * // Transaction successful
305
+ * setTransactionHash(result.transactionHash);
306
+ *
307
+ * if (result.shouldRedirect && result.redirectUrl) {
308
+ * // Handle post-transaction redirect
309
+ * Linking.openURL(result.redirectUrl);
310
+ * }
311
+ * } else {
312
+ * // Transaction failed but didn't throw
313
+ * setError(result.error || 'Transaction failed');
314
+ * }
315
+ * } catch (error) {
316
+ * // Handle different error types
317
+ * if (error.message.includes('expired')) {
318
+ * // Token expired - redirect to login
319
+ * navigation.navigate('Login');
320
+ * } else if (error.message.includes('network')) {
321
+ * // Network error - suggest retry
322
+ * setError('Network error. Please try again.');
323
+ * } else {
324
+ * // Other errors
325
+ * setError(error.message);
326
+ * }
327
+ * }
328
+ * ```
329
+ *
330
+ * @see {@link SubmissionResult} for detailed result structure
131
331
  */
132
- const signTransactionWithJWT = useCallback(async (jwt: string): Promise<TransactionSigningResult> => {
332
+ const signAndSubmitTransactionWithJWT = useCallback(async (jwt: string): Promise<SubmissionResult> => {
133
333
  if (!isSignerInitialized || !signerSDKRef.current) {
134
334
  throw new Error('Transaction signer not initialized');
135
335
  }
@@ -138,128 +338,84 @@ export const useTransactionSigner = () => {
138
338
  }
139
339
 
140
340
  try {
141
- console.log('[useTransactionSigner] Starting JWT-based transaction signing...');
142
-
143
- // Create URLSearchParams from JWT token (matching web frontend)
144
- const searchParams = new URLSearchParams();
145
- searchParams.set('jwt', jwt);
341
+ // Use the actual SDK method that handles the complete sign + submit flow
342
+ const submissionResult = await signerSDKRef.current.signAndSubmitPersTransaction(jwt);
146
343
 
147
- // Step 1: Authenticate with JWT (handles tenant setup, project keys automatically)
148
- console.log('[useTransactionSigner] Authenticating with JWT...');
149
- const authResult = await signerSDKRef.current.authenticateWithJWT(searchParams);
150
-
151
- if (!authResult) {
152
- throw new Error('JWT authentication failed - no valid token found');
153
- }
154
-
155
- if (authResult.isExpired) {
156
- throw new Error('JWT token is expired');
157
- }
158
-
159
- console.log('[useTransactionSigner] JWT authentication successful:', authResult.user.identifier);
160
-
161
- // Step 2: Extract transaction ID from JWT
162
- const jwtParts = jwt.split('.');
163
- if (jwtParts.length !== 3) {
164
- throw new Error('Invalid JWT token format');
165
- }
166
-
167
- const payload = JSON.parse(atob(jwtParts[1]));
168
- const transactionId = payload.transactionId;
169
-
170
- if (!transactionId) {
171
- throw new Error('No transaction ID found in JWT token');
172
- }
173
-
174
- console.log('[useTransactionSigner] Found transaction ID:', transactionId);
175
-
176
- // Step 3: Sign transaction using authenticated user
177
- console.log('[useTransactionSigner] Signing transaction...');
178
- const signingResult = await signerSDKRef.current.signPersTransaction(
179
- authResult.user,
180
- transactionId
181
- );
182
-
183
- console.log('[useTransactionSigner] Transaction signing result:', signingResult);
184
-
185
- return {
186
- success: signingResult.success,
187
- transactionHash: signingResult.transactionHash,
188
- error: signingResult.error
189
- };
344
+ return submissionResult;
190
345
 
191
346
  } catch (error) {
192
347
  console.error('[useTransactionSigner] JWT transaction signing failed:', error);
193
- return {
194
- success: false,
195
- error: `Transaction signing failed: ${error}`
196
- };
348
+ throw error; // Re-throw to maintain error handling upstream
197
349
  }
198
350
  }, [isSignerInitialized]);
199
351
 
200
- /**
201
- * Manual user authentication (fallback method)
202
- */
203
- const authenticateUser = useCallback(async (identifier: string): Promise<SignerAuthenticatedUser | null> => {
204
- if (!isSignerInitialized || !signerSDKRef.current) {
205
- throw new Error('Transaction signer not initialized');
206
- }
207
-
208
- try {
209
- console.log('[useTransactionSigner] Manual user authentication:', identifier);
210
- const user = await signerSDKRef.current.authenticateUser(identifier);
211
- console.log('[useTransactionSigner] Manual authentication successful');
212
- return user;
213
- } catch (error) {
214
- console.error('[useTransactionSigner] Manual authentication failed:', error);
215
- return null;
216
- }
217
- }, [isSignerInitialized]);
218
-
219
- /**
220
- * Legacy method for backward compatibility
221
- * @deprecated Use signTransactionWithJWT instead
222
- */
223
- const signTransaction = useCallback(async (jwt: string): Promise<TransactionSigningResult> => {
224
- console.warn('[useTransactionSigner] signTransaction is deprecated, use signTransactionWithJWT');
225
- return signTransactionWithJWT(jwt);
226
- }, [signTransactionWithJWT]);
227
-
228
352
  return {
229
353
  /**
230
- * Sign a blockchain transaction using JWT token (recommended method)
231
- */
232
- signTransactionWithJWT,
233
-
234
- /**
235
- * Legacy transaction signing method
236
- * @deprecated Use signTransactionWithJWT instead
237
- */
238
- signTransaction,
239
-
240
- /**
241
- * Manual user authentication (for advanced use cases)
354
+ * Sign and submit a blockchain transaction using JWT token
355
+ *
356
+ * Main method for executing blockchain transactions. Handles complete flow
357
+ * from authentication to blockchain submission in a single call.
358
+ *
359
+ * @param {string} jwt - JWT token with transaction and user data
360
+ * @returns {Promise<SubmissionResult>} Transaction result with hash and status
242
361
  */
243
- authenticateUser,
362
+ signAndSubmitTransactionWithJWT,
244
363
 
245
364
  /**
246
- * Whether the transaction signer has been initialized
365
+ * Whether the transaction signer SDK has been successfully initialized
366
+ *
367
+ * Use this to show loading states while the signer is being set up.
368
+ * When `false`, the signer is still initializing and transactions cannot be processed.
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * const { isSignerInitialized } = useTransactionSigner();
373
+ *
374
+ * if (!isSignerInitialized) {
375
+ * return <LoadingSpinner text="Initializing signer..." />;
376
+ * }
377
+ * ```
247
378
  */
248
379
  isSignerInitialized,
249
380
 
250
381
  /**
251
- * Whether transaction signing is available (all requirements met)
382
+ * Whether blockchain transaction signing is fully available
383
+ *
384
+ * This combines multiple checks: SDK availability, initialization status,
385
+ * and configuration validity. Use this to enable/disable transaction buttons.
386
+ *
387
+ * Returns `true` only when:
388
+ * - PERS Signer SDK is installed and available
389
+ * - Signer has been successfully initialized
390
+ * - All required dependencies are loaded
391
+ *
392
+ * @example
393
+ * ```typescript
394
+ * const { isSignerAvailable } = useTransactionSigner();
395
+ *
396
+ * return (
397
+ * <TouchableOpacity
398
+ * disabled={!isSignerAvailable}
399
+ * style={[styles.button, !isSignerAvailable && styles.disabled]}
400
+ * >
401
+ * <Text>{isSignerAvailable ? 'Sign Transaction' : 'Signer Unavailable'}</Text>
402
+ * </TouchableOpacity>
403
+ * );
404
+ * ```
252
405
  */
253
406
  isSignerAvailable: isSignerInitialized && !!createPersSignerSDK,
254
407
  };
255
408
  };
256
409
 
257
410
  /**
258
- * Type definition for the transaction signer hook
259
- */
260
- export type TransactionSignerHook = ReturnType<typeof useTransactionSigner>;
261
-
262
- /**
263
- * Export the transaction signing result type for external usage
411
+ * Type exports for external usage
412
+ *
413
+ * These types are re-exported from the PERS Signer SDK for convenience
414
+ * when working with transaction signing in React Native applications.
415
+ *
416
+ * @see {@link SubmissionResult} - Complete transaction submission result
417
+ * @see {@link AuthenticatedUser} - User authentication data structure
418
+ * @see {@link TransactionSigningResult} - Transaction signing result details
419
+ * @see {@link TransactionSignerHook} - Hook return interface
264
420
  */
265
- export type { TransactionSigningResult, SignerAuthenticatedUser, AuthenticationResult };
421
+ export type { SubmissionResult, AuthenticatedUser, TransactionSigningResult };
@@ -4,7 +4,8 @@ import { useTransactionSigner } from './useTransactionSigner';
4
4
  import type {
5
5
  TransactionRequestDTO,
6
6
  TransactionRequestResponseDTO,
7
- TransactionDTO
7
+ TransactionDTO,
8
+ TransactionRole
8
9
  } from '@explorins/pers-shared';
9
10
  import type { TransactionPaginationParams } from '@explorins/pers-sdk/transaction';
10
11
 
@@ -46,7 +47,7 @@ import type { TransactionPaginationParams } from '@explorins/pers-sdk/transactio
46
47
  */
47
48
  export const useTransactions = () => {
48
49
  const { sdk, isInitialized, isAuthenticated } = usePersSDK();
49
- const { signTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
50
+ const { signAndSubmitTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
50
51
 
51
52
  if (!isAuthenticated && isInitialized) {
52
53
  console.warn('SDK not authenticated. Some transaction operations may fail.');
@@ -97,7 +98,7 @@ export const useTransactions = () => {
97
98
  }
98
99
 
99
100
  // Automatically sign the transaction using the authToken
100
- const signingResult = await signTransactionWithJWT(txToken);
101
+ const signingResult = await signAndSubmitTransactionWithJWT(txToken);
101
102
 
102
103
  if (signingResult.success) {
103
104
  console.log('[useTransactions] Transaction signed successfully:', signingResult.transactionHash);
@@ -120,7 +121,7 @@ export const useTransactions = () => {
120
121
  console.error('Failed to create transaction:', error);
121
122
  throw error;
122
123
  }
123
- }, [sdk, isInitialized, signTransactionWithJWT, isSignerAvailable]);
124
+ }, [sdk, isInitialized, signAndSubmitTransactionWithJWT, isSignerAvailable]);
124
125
 
125
126
  /**
126
127
  * Retrieves a specific transaction by its ID
@@ -152,26 +153,27 @@ export const useTransactions = () => {
152
153
  }, [sdk, isInitialized]);
153
154
 
154
155
  /**
155
- * Retrieves transaction history for the authenticated user, filtered by type
156
+ * Retrieves transaction history for the authenticated user, filtered by role
156
157
  *
157
- * @param type - Transaction type filter (defaults to 'all')
158
+ * @param role - Optional transaction role filter (TransactionRole.SENDER, TransactionRole.RECIPIENT)
158
159
  * @returns Promise resolving to array of user's transactions
159
160
  * @throws Error if SDK is not initialized
160
161
  *
161
162
  * @example
162
163
  * ```typescript
163
164
  * const { getUserTransactionHistory } = useTransactions();
164
- * const transactions = await getUserTransactionHistory('credit');
165
- * console.log('Credit transactions:', transactions);
165
+ * const sentTransactions = await getUserTransactionHistory(TransactionRole.SENDER);
166
+ * const allTransactions = await getUserTransactionHistory(); // No filter
166
167
  * ```
167
168
  */
168
- const getUserTransactionHistory = useCallback(async (type: string = 'all'): Promise<TransactionDTO[]> => {
169
+ const getUserTransactionHistory = useCallback(async (role?: TransactionRole): Promise<TransactionDTO[]> => {
170
+
169
171
  if (!isInitialized || !sdk) {
170
172
  throw new Error('SDK not initialized. Call initialize() first.');
171
173
  }
172
174
 
173
175
  try {
174
- const result = await sdk.transactions.getUserTransactionHistory(type);
176
+ const result = await sdk.transactions.getUserTransactionHistory(role);
175
177
  console.log('Transaction history fetched successfully:', result);
176
178
  return result;
177
179
  } catch (error) {
@@ -187,7 +189,6 @@ export const useTransactions = () => {
187
189
 
188
190
  try {
189
191
  const result = await sdk.transactions.getTenantTransactions();
190
- console.log('Tenant transactions fetched successfully:', result);
191
192
  return result;
192
193
  } catch (error) {
193
194
  console.error('Failed to fetch tenant transactions:', error);
@@ -9,7 +9,14 @@ import type {
9
9
  } from '@explorins/pers-sdk/web3';
10
10
  import type { ChainData } from '@explorins/pers-sdk/web3-chain';
11
11
 
12
- interface WalletInfo {
12
+ /**
13
+ * Wallet information interface
14
+ *
15
+ * @interface WalletInfo
16
+ * @property {string | null} address - Wallet address if connected
17
+ * @property {boolean} isConnected - Whether wallet is connected
18
+ */
19
+ export interface WalletInfo {
13
20
  address: string | null;
14
21
  isConnected: boolean;
15
22
  }