@explorins/pers-sdk-react-native 1.5.13 → 1.5.16
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/useTransactionSigner.d.ts +23 -20
- package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.js +105 -264
- package/dist/index.js +106 -265
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/hooks/useTransactionSigner.ts +131 -301
- package/dist/react-native.esm-BtyCg4n1.js +0 -10062
- package/dist/react-native.esm-BtyCg4n1.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@explorins/pers-sdk-react-native",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.16",
|
|
4
4
|
"description": "React Native SDK for PERS Platform - Tourism Loyalty System with Manager Pattern Architecture",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@dfns/sdk-react-native": "^0.8.1",
|
|
36
36
|
"@explorins/pers-sdk": "^1.6.3",
|
|
37
37
|
"@explorins/pers-shared": "^2.1.40",
|
|
38
|
-
"@explorins/pers-signer": "^1.0.
|
|
38
|
+
"@explorins/pers-signer": "^1.0.11",
|
|
39
39
|
"@explorins/web3-ts": "^0.3.75",
|
|
40
40
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
41
41
|
"buffer": "^6.0.3",
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { useCallback, useState, useRef, useEffect } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { UserDTO, AdminDTO } from '@explorins/pers-shared';
|
|
4
3
|
|
|
5
4
|
// Dynamic import the signer SDK to avoid build issues with static dependencies
|
|
6
|
-
let createPersSignerSDK: ((config: PersSignerConfig) => Promise<
|
|
5
|
+
let createPersSignerSDK: ((config: PersSignerConfig) => Promise<PersSignerSDKInstance>) | null = null;
|
|
7
6
|
try {
|
|
8
7
|
const signerModule = require('@explorins/pers-signer/react-native');
|
|
9
8
|
createPersSignerSDK = signerModule.createPersSignerSDK;
|
|
@@ -13,25 +12,22 @@ try {
|
|
|
13
12
|
console.warn('[useTransactionSigner] Real blockchain signing will not be available');
|
|
14
13
|
}
|
|
15
14
|
|
|
15
|
+
// Simplified configuration matching web frontend
|
|
16
16
|
interface PersSignerConfig {
|
|
17
|
-
tenantId?: string; // Multi-tenant identifier
|
|
18
17
|
ethersProviderUrl?: string; // Custom blockchain provider
|
|
19
|
-
// webAuthnProvider: WebAuthnProvider; // Platform-specific WebAuthn provider
|
|
20
|
-
// Optional overrides for advanced use cases
|
|
21
|
-
apiUrl?: string; // Override default signer API URL (defaults to signer-api.pers.ninja)
|
|
22
|
-
relyingPartyName?: string; // Override default relying party name (defaults to 'PERS Signer')
|
|
23
18
|
}
|
|
24
19
|
|
|
20
|
+
// Simplified SDK interface matching web frontend
|
|
25
21
|
interface PersSignerSDKInstance {
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
authenticateWithJWT: (searchParams: URLSearchParams) => Promise<AuthenticationResult | null>;
|
|
23
|
+
authenticateUser: (identifier: string) => Promise<SignerAuthenticatedUser>;
|
|
24
|
+
signPersTransaction: (user: SignerAuthenticatedUser, transactionId: string) => Promise<SigningResult>;
|
|
28
25
|
}
|
|
29
26
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
persAccessToken?: string;
|
|
27
|
+
// Types matching web frontend
|
|
28
|
+
interface AuthenticationResult {
|
|
29
|
+
user: SignerAuthenticatedUser;
|
|
30
|
+
isExpired: boolean;
|
|
35
31
|
}
|
|
36
32
|
|
|
37
33
|
interface SignerAuthenticatedUser {
|
|
@@ -43,37 +39,9 @@ interface SignerAuthenticatedUser {
|
|
|
43
39
|
interface SigningResult {
|
|
44
40
|
success: boolean;
|
|
45
41
|
transactionHash?: string;
|
|
46
|
-
signature?: string;
|
|
47
42
|
error?: string;
|
|
48
43
|
}
|
|
49
44
|
|
|
50
|
-
/**
|
|
51
|
-
* Utility to decode JWT and extract user information
|
|
52
|
-
* This will be used to extract user data for the signer
|
|
53
|
-
*/
|
|
54
|
-
const extractUserInfoFromJWT = async (jwt: string): Promise<{ userId?: string; email?: string; sub?: string }> => {
|
|
55
|
-
try {
|
|
56
|
-
// Dynamically import jwt-decode to avoid bundling issues
|
|
57
|
-
const { jwtDecode } = await import('jwt-decode');
|
|
58
|
-
const decoded = jwtDecode<{
|
|
59
|
-
sub?: string;
|
|
60
|
-
email?: string;
|
|
61
|
-
user_id?: string;
|
|
62
|
-
userId?: string;
|
|
63
|
-
uid?: string;
|
|
64
|
-
}>(jwt);
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
userId: decoded.user_id || decoded.userId || decoded.uid || decoded.sub,
|
|
68
|
-
email: decoded.email,
|
|
69
|
-
sub: decoded.sub
|
|
70
|
-
};
|
|
71
|
-
} catch (error) {
|
|
72
|
-
console.warn('[useTransactionSigner] Failed to decode JWT:', error);
|
|
73
|
-
return {};
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
|
|
77
45
|
// Define our own result type that's compatible with both SDK and our usage
|
|
78
46
|
interface TransactionSigningResult {
|
|
79
47
|
success: boolean;
|
|
@@ -88,24 +56,17 @@ const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0
|
|
|
88
56
|
/**
|
|
89
57
|
* React Native hook for blockchain transaction signing using PERS Signer SDK
|
|
90
58
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
59
|
+
* Simplified interface matching web frontend - uses high-level SDK methods
|
|
60
|
+
* that handle all complexity internally (tenant setup, project keys, etc.).
|
|
93
61
|
*
|
|
94
62
|
* @example
|
|
95
63
|
* ```typescript
|
|
96
64
|
* function TransactionComponent() {
|
|
97
|
-
* const {
|
|
65
|
+
* const { signTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
|
|
98
66
|
*
|
|
99
|
-
*
|
|
100
|
-
* initializeSigner({
|
|
101
|
-
* tenantId: 'my-tenant',
|
|
102
|
-
* ethersProviderUrl: 'https://sepolia.infura.io/v3/...'
|
|
103
|
-
* });
|
|
104
|
-
* }, []);
|
|
105
|
-
*
|
|
106
|
-
* const handleSign = async () => {
|
|
67
|
+
* const handleSign = async (jwtFromRedemption: string) => {
|
|
107
68
|
* try {
|
|
108
|
-
* const result = await
|
|
69
|
+
* const result = await signTransactionWithJWT(jwtFromRedemption);
|
|
109
70
|
* if (result.success) {
|
|
110
71
|
* console.log('Transaction signed:', result.transactionHash);
|
|
111
72
|
* }
|
|
@@ -123,294 +84,163 @@ const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0
|
|
|
123
84
|
* ```
|
|
124
85
|
*/
|
|
125
86
|
export const useTransactionSigner = () => {
|
|
126
|
-
const {
|
|
87
|
+
const { isInitialized, isAuthenticated, user } = usePersSDK();
|
|
127
88
|
const [isSignerInitialized, setIsSignerInitialized] = useState(false);
|
|
128
89
|
const signerSDKRef = useRef<PersSignerSDKInstance | null>(null);
|
|
129
90
|
|
|
130
|
-
// Auto-initialize signer when
|
|
91
|
+
// Auto-initialize signer SDK when PERS SDK is ready
|
|
131
92
|
useEffect(() => {
|
|
132
|
-
console.log('[useTransactionSigner]
|
|
133
|
-
isInitialized,
|
|
134
|
-
isAuthenticated,
|
|
135
|
-
hasUser: !!user,
|
|
136
|
-
isSignerInitialized,
|
|
137
|
-
hasSDK: !!sdk,
|
|
138
|
-
hasAuthProvider: !!authProvider,
|
|
139
|
-
hasCreatePersSignerSDK: !!createPersSignerSDK
|
|
140
|
-
});
|
|
93
|
+
console.log('[useTransactionSigner] Auto-initializing signer SDK...');
|
|
141
94
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
// Get configuration from the PERS SDK
|
|
149
|
-
const sdkConfig = (sdk as any).config || {};
|
|
150
|
-
console.log('[useTransactionSigner] SDK config:', sdkConfig);
|
|
151
|
-
|
|
152
|
-
// Try to extract tenantId from JWT token if available
|
|
153
|
-
let tenantIdFromJWT: string | undefined;
|
|
154
|
-
let authToken: string | null | undefined;
|
|
155
|
-
if (authProvider.getToken) {
|
|
156
|
-
try {
|
|
157
|
-
authToken = await authProvider.getToken();
|
|
158
|
-
if (authToken) {
|
|
159
|
-
// Decode JWT to get tenant information
|
|
160
|
-
const tokenParts = authToken.split('.');
|
|
161
|
-
if (tokenParts.length >= 2) {
|
|
162
|
-
const payload = JSON.parse(atob(tokenParts[1]));
|
|
163
|
-
console.log('[useTransactionSigner] JWT payload decoded:', payload);
|
|
164
|
-
|
|
165
|
-
// Look for tenant ID in various possible fields
|
|
166
|
-
tenantIdFromJWT = payload.tenantId || payload.tenant_id || payload.tenant;
|
|
167
|
-
if (tenantIdFromJWT) {
|
|
168
|
-
console.log('[useTransactionSigner] Found tenant ID in JWT:', tenantIdFromJWT);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
} catch (e) {
|
|
173
|
-
console.warn('[useTransactionSigner] Failed to decode JWT for tenant ID:', e);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// For React Native, we should get tenantId from JWT, then user/auth context, then config
|
|
178
|
-
const userTenantId = (user as any).tenantId || (user as any).tenant_id;
|
|
179
|
-
const configTenantId = sdkConfig.tenantId || 'vq-demo';
|
|
180
|
-
const tenantId = tenantIdFromJWT || userTenantId || configTenantId;
|
|
181
|
-
|
|
182
|
-
console.log('[useTransactionSigner] Extracted tenant ID:', tenantId, 'from JWT:', tenantIdFromJWT, 'user:', userTenantId, 'or config:', configTenantId);
|
|
183
|
-
|
|
184
|
-
// Don't use apiProjectKey since we'll get it via tenant initialization
|
|
185
|
-
await initializeSigner({
|
|
186
|
-
tenantId: tenantId,
|
|
187
|
-
ethersProviderUrl: DEFAULT_ETHERS_PROVIDER
|
|
188
|
-
});
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.error('[useTransactionSigner] Auto-initialization failed:', error);
|
|
191
|
-
}
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
autoInitialize();
|
|
195
|
-
}
|
|
196
|
-
}, [isInitialized, isAuthenticated, user, isSignerInitialized, sdk, authProvider]);
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Initialize the blockchain signer with configuration
|
|
200
|
-
*
|
|
201
|
-
* @param config - Signer configuration options
|
|
202
|
-
* @param config.tenantId - Multi-tenant identifier for the signer
|
|
203
|
-
* @param config.projectKey - PERS project API key for authentication
|
|
204
|
-
* @param config.ethersProviderUrl - Custom blockchain provider URL
|
|
205
|
-
*
|
|
206
|
-
* @example
|
|
207
|
-
* ```typescript
|
|
208
|
-
* await initializeSigner({
|
|
209
|
-
* tenantId: 'my-tenant-id',
|
|
210
|
-
* projectKey: 'your-pers-api-key',
|
|
211
|
-
* ethersProviderUrl: 'https://sepolia.infura.io/v3/your-key'
|
|
212
|
-
* });
|
|
213
|
-
* ```
|
|
214
|
-
*/
|
|
215
|
-
const initializeSigner = useCallback(async (config?: {
|
|
216
|
-
tenantId?: string;
|
|
217
|
-
projectKey?: string;
|
|
218
|
-
ethersProviderUrl?: string;
|
|
219
|
-
}) => {
|
|
220
|
-
if (!createPersSignerSDK) {
|
|
221
|
-
throw new Error('PERS Signer SDK not available. Please ensure dependencies are properly installed.');
|
|
222
|
-
}
|
|
95
|
+
const initializeSignerSDK = async () => {
|
|
96
|
+
if (!createPersSignerSDK) {
|
|
97
|
+
console.warn('[useTransactionSigner] Signer SDK not available');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
223
100
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
});
|
|
237
|
-
console.log('[useTransactionSigner] PERS service configured with project key');
|
|
238
|
-
|
|
239
|
-
// Verify configuration
|
|
240
|
-
const persConfig = (PersService as any).getConfig();
|
|
241
|
-
console.log('[useTransactionSigner] PERS service config after configuration:', persConfig);
|
|
242
|
-
} catch (configError) {
|
|
243
|
-
console.error('[useTransactionSigner] Failed to configure PERS service:', configError);
|
|
244
|
-
}
|
|
245
|
-
} else if (config?.tenantId) {
|
|
246
|
-
console.log('[useTransactionSigner] No project key provided, will initialize tenant with tenantId:', config.tenantId);
|
|
247
|
-
try {
|
|
248
|
-
// Import and initialize tenant environment to get project key
|
|
249
|
-
const { PersService } = await import('@explorins/pers-signer/react-native');
|
|
250
|
-
console.log('[useTransactionSigner] Initializing tenant for tenantId:', config.tenantId);
|
|
251
|
-
|
|
252
|
-
// We need to set the auth token first for tenant initialization
|
|
253
|
-
let authToken: string | null | undefined;
|
|
254
|
-
if (authProvider) {
|
|
255
|
-
try {
|
|
256
|
-
authToken = await authProvider.getToken();
|
|
257
|
-
if (authToken) {
|
|
258
|
-
console.log('[useTransactionSigner] Setting auth token for tenant initialization');
|
|
259
|
-
(PersService as any).configure({
|
|
260
|
-
token: authToken
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
} catch (tokenError) {
|
|
264
|
-
console.warn('[useTransactionSigner] Could not get auth token for tenant initialization:', tokenError);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
await (PersService as any).initializeTenant(config.tenantId, authToken);
|
|
269
|
-
console.log('[useTransactionSigner] Tenant initialized successfully');
|
|
270
|
-
|
|
271
|
-
// Get tenant data to extract project key manually
|
|
272
|
-
try {
|
|
273
|
-
const tenantData = await (PersService as any).getTenantById(config.tenantId, authToken);
|
|
274
|
-
console.log('[useTransactionSigner] Tenant data retrieved:', tenantData);
|
|
275
|
-
|
|
276
|
-
// Extract and set project key manually if initializeTenant didn't set it
|
|
277
|
-
const projectKey = tenantData.projectApiKey || tenantData.projectKey || tenantData.apiKey;
|
|
278
|
-
if (projectKey) {
|
|
279
|
-
console.log('[useTransactionSigner] Setting project key manually:', projectKey);
|
|
280
|
-
(PersService as any).configure({
|
|
281
|
-
token: authToken,
|
|
282
|
-
projectKey: projectKey
|
|
283
|
-
});
|
|
284
|
-
} else {
|
|
285
|
-
console.warn('[useTransactionSigner] No project key found in tenant data:', tenantData);
|
|
286
|
-
}
|
|
287
|
-
} catch (tenantError) {
|
|
288
|
-
console.error('[useTransactionSigner] Failed to retrieve tenant data for project key:', tenantError);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Verify configuration
|
|
292
|
-
const persConfig = (PersService as any).getConfig();
|
|
293
|
-
console.log('[useTransactionSigner] PERS service config after tenant initialization:', persConfig);
|
|
294
|
-
} catch (configError) {
|
|
295
|
-
console.error('[useTransactionSigner] Failed to initialize tenant:', configError);
|
|
296
|
-
}
|
|
101
|
+
try {
|
|
102
|
+
console.log('[useTransactionSigner] Creating PERS Signer SDK...');
|
|
103
|
+
const signerSDK = await createPersSignerSDK({
|
|
104
|
+
ethersProviderUrl: DEFAULT_ETHERS_PROVIDER
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
signerSDKRef.current = signerSDK;
|
|
108
|
+
setIsSignerInitialized(true);
|
|
109
|
+
console.log('[useTransactionSigner] PERS Signer SDK initialized successfully');
|
|
110
|
+
|
|
111
|
+
} catch (error) {
|
|
112
|
+
console.error('[useTransactionSigner] Failed to initialize signer SDK:', error);
|
|
297
113
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
signerSDKRef.current = signerSDK;
|
|
305
|
-
setIsSignerInitialized(true);
|
|
306
|
-
console.log('[useTransactionSigner] PERS Signer SDK initialized successfully');
|
|
307
|
-
|
|
308
|
-
} catch (error) {
|
|
309
|
-
console.error('[useTransactionSigner] Failed to initialize transaction signer:', error);
|
|
310
|
-
throw new Error(`Signer initialization failed: ${error}`);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (!isSignerInitialized) {
|
|
117
|
+
initializeSignerSDK();
|
|
311
118
|
}
|
|
312
|
-
}, [
|
|
119
|
+
}, [isSignerInitialized]);
|
|
313
120
|
|
|
314
121
|
/**
|
|
315
|
-
* Sign a blockchain transaction using
|
|
316
|
-
*
|
|
317
|
-
* @param jwt - JWT token containing transaction information and user context
|
|
318
|
-
* @returns Promise resolving to signing result with transaction hash
|
|
122
|
+
* Sign a blockchain transaction using JWT token (matching web frontend pattern)
|
|
319
123
|
*
|
|
320
|
-
*
|
|
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
|
|
321
128
|
*
|
|
322
|
-
* @
|
|
323
|
-
*
|
|
324
|
-
* try {
|
|
325
|
-
* const result = await signTransaction(jwtToken);
|
|
326
|
-
* if (result.success) {
|
|
327
|
-
* console.log('Signed transaction hash:', result.transactionHash);
|
|
328
|
-
* } else {
|
|
329
|
-
* console.error('Signing failed:', result.error);
|
|
330
|
-
* }
|
|
331
|
-
* } catch (error) {
|
|
332
|
-
* console.error('Signing error:', error);
|
|
333
|
-
* }
|
|
334
|
-
* ```
|
|
129
|
+
* @param jwt - JWT token from redemption flow containing transaction ID
|
|
130
|
+
* @returns Promise resolving to signing result with transaction hash
|
|
335
131
|
*/
|
|
336
|
-
const
|
|
337
|
-
if (!isInitialized || !sdk) {
|
|
338
|
-
throw new Error('SDK not initialized. Call initialize() first.');
|
|
339
|
-
}
|
|
340
|
-
if (!isAuthenticated || !user) {
|
|
341
|
-
throw new Error('User must be authenticated to sign transactions.');
|
|
342
|
-
}
|
|
132
|
+
const signTransactionWithJWT = useCallback(async (jwt: string): Promise<TransactionSigningResult> => {
|
|
343
133
|
if (!isSignerInitialized || !signerSDKRef.current) {
|
|
344
|
-
throw new Error('Transaction signer not initialized
|
|
134
|
+
throw new Error('Transaction signer not initialized');
|
|
345
135
|
}
|
|
346
136
|
if (!createPersSignerSDK) {
|
|
347
137
|
throw new Error('PERS Signer SDK not available. Blockchain signing is not supported.');
|
|
348
138
|
}
|
|
349
139
|
|
|
350
140
|
try {
|
|
351
|
-
console.log('[useTransactionSigner]
|
|
141
|
+
console.log('[useTransactionSigner] Starting JWT-based transaction signing...');
|
|
352
142
|
|
|
353
|
-
//
|
|
354
|
-
const
|
|
143
|
+
// Create URLSearchParams from JWT token (matching web frontend)
|
|
144
|
+
const searchParams = new URLSearchParams();
|
|
145
|
+
searchParams.set('jwt', jwt);
|
|
355
146
|
|
|
356
|
-
//
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
identifier: currentUser.email || currentUser.id || jwtUserInfo.userId || jwtUserInfo.sub || `user-${Date.now()}`,
|
|
360
|
-
email: currentUser.email || jwtUserInfo.email,
|
|
361
|
-
id: currentUser.id || jwtUserInfo.userId
|
|
362
|
-
};
|
|
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);
|
|
363
150
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
console.log('[useTransactionSigner] PERS access token extracted:', persAccessToken ? 'Token found' : 'No token');
|
|
151
|
+
if (!authResult) {
|
|
152
|
+
throw new Error('JWT authentication failed - no valid token found');
|
|
153
|
+
}
|
|
368
154
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
...signerUserInfo,
|
|
373
|
-
persAccessToken: persAccessToken || undefined
|
|
374
|
-
});
|
|
155
|
+
if (authResult.isExpired) {
|
|
156
|
+
throw new Error('JWT token is expired');
|
|
157
|
+
}
|
|
375
158
|
|
|
376
|
-
|
|
377
|
-
console.log('[useTransactionSigner] Signing PERS transaction with JWT containing transaction data');
|
|
378
|
-
const result = await signerSDKRef.current.signPersTransaction(signerUser, jwt);
|
|
159
|
+
console.log('[useTransactionSigner] JWT authentication successful:', authResult.user.identifier);
|
|
379
160
|
|
|
380
|
-
//
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
error: result.error
|
|
386
|
-
};
|
|
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
|
+
}
|
|
387
166
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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');
|
|
392
172
|
}
|
|
393
173
|
|
|
394
|
-
|
|
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
|
+
};
|
|
190
|
+
|
|
395
191
|
} catch (error) {
|
|
396
|
-
console.error('[useTransactionSigner]
|
|
192
|
+
console.error('[useTransactionSigner] JWT transaction signing failed:', error);
|
|
397
193
|
return {
|
|
398
194
|
success: false,
|
|
399
195
|
error: `Transaction signing failed: ${error}`
|
|
400
196
|
};
|
|
401
197
|
}
|
|
402
|
-
}, [
|
|
198
|
+
}, [isSignerInitialized]);
|
|
199
|
+
|
|
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]);
|
|
403
227
|
|
|
404
228
|
return {
|
|
405
229
|
/**
|
|
406
|
-
* Sign a blockchain transaction
|
|
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
|
|
407
237
|
*/
|
|
408
238
|
signTransaction,
|
|
409
239
|
|
|
410
240
|
/**
|
|
411
|
-
*
|
|
241
|
+
* Manual user authentication (for advanced use cases)
|
|
412
242
|
*/
|
|
413
|
-
|
|
243
|
+
authenticateUser,
|
|
414
244
|
|
|
415
245
|
/**
|
|
416
246
|
* Whether the transaction signer has been initialized
|
|
@@ -420,7 +250,7 @@ export const useTransactionSigner = () => {
|
|
|
420
250
|
/**
|
|
421
251
|
* Whether transaction signing is available (all requirements met)
|
|
422
252
|
*/
|
|
423
|
-
isSignerAvailable:
|
|
253
|
+
isSignerAvailable: isSignerInitialized && !!createPersSignerSDK,
|
|
424
254
|
};
|
|
425
255
|
};
|
|
426
256
|
|
|
@@ -432,4 +262,4 @@ export type TransactionSignerHook = ReturnType<typeof useTransactionSigner>;
|
|
|
432
262
|
/**
|
|
433
263
|
* Export the transaction signing result type for external usage
|
|
434
264
|
*/
|
|
435
|
-
export type { TransactionSigningResult };
|
|
265
|
+
export type { TransactionSigningResult, SignerAuthenticatedUser, AuthenticationResult };
|