@explorins/pers-sdk-react-native 2.0.5 → 2.1.1

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.
@@ -1,5 +1,6 @@
1
- import { useCallback } from 'react';
1
+ import { useCallback, useMemo } from 'react';
2
2
  import { usePersSDK } from '../providers/PersSDKProvider';
3
+ import { Web3Manager } from '@explorins/pers-sdk/web3';
3
4
  /**
4
5
  * React hook for Web3 operations in the PERS SDK
5
6
  *
@@ -55,6 +56,15 @@ export const useWeb3 = () => {
55
56
  if (!isAuthenticated && isInitialized) {
56
57
  console.warn('SDK not authenticated. Some web3 operations may fail.');
57
58
  }
59
+ /**
60
+ * Create Web3Manager instance lazily
61
+ * Web3Manager is now separate from PersSDK since v2.0.11+
62
+ */
63
+ const web3 = useMemo(() => {
64
+ if (!sdk)
65
+ return null;
66
+ return new Web3Manager(sdk.api());
67
+ }, [sdk]);
58
68
  /**
59
69
  * Retrieves token balance for a specific wallet and contract
60
70
  *
@@ -75,18 +85,18 @@ export const useWeb3 = () => {
75
85
  * ```
76
86
  */
77
87
  const getTokenBalance = useCallback(async (request) => {
78
- if (!isInitialized || !sdk) {
88
+ if (!isInitialized || !web3) {
79
89
  throw new Error('SDK not initialized. Call initialize() first.');
80
90
  }
81
91
  try {
82
- const result = await sdk.web3.getTokenBalance(request);
92
+ const result = await web3.getTokenBalance(request);
83
93
  return result;
84
94
  }
85
95
  catch (error) {
86
96
  console.error('Failed to fetch token balance:', error);
87
97
  throw error;
88
98
  }
89
- }, [sdk, isInitialized]);
99
+ }, [web3, isInitialized]);
90
100
  /**
91
101
  * Retrieves metadata for a specific token (useful for NFTs)
92
102
  *
@@ -107,83 +117,83 @@ export const useWeb3 = () => {
107
117
  * ```
108
118
  */
109
119
  const getTokenMetadata = useCallback(async (request) => {
110
- if (!isInitialized || !sdk) {
120
+ if (!isInitialized || !web3) {
111
121
  throw new Error('SDK not initialized. Call initialize() first.');
112
122
  }
113
123
  try {
114
- const result = await sdk.web3.getTokenMetadata(request);
124
+ const result = await web3.getTokenMetadata(request);
115
125
  return result;
116
126
  }
117
127
  catch (error) {
118
128
  console.error('Failed to fetch token metadata:', error);
119
129
  throw error;
120
130
  }
121
- }, [sdk, isInitialized]);
131
+ }, [web3, isInitialized]);
122
132
  const getTokenCollection = useCallback(async (request) => {
123
- if (!isInitialized || !sdk) {
133
+ if (!isInitialized || !web3) {
124
134
  throw new Error('SDK not initialized. Call initialize() first.');
125
135
  }
126
136
  try {
127
- const result = await sdk.web3.getTokenCollection(request);
137
+ const result = await web3.getTokenCollection(request);
128
138
  return result;
129
139
  }
130
140
  catch (error) {
131
141
  console.error('Failed to fetch token collection:', error);
132
142
  throw error;
133
143
  }
134
- }, [sdk, isInitialized]);
144
+ }, [web3, isInitialized]);
135
145
  const resolveIPFSUrl = useCallback(async (url, chainId) => {
136
- if (!isInitialized || !sdk) {
146
+ if (!isInitialized || !web3) {
137
147
  throw new Error('SDK not initialized. Call initialize() first.');
138
148
  }
139
149
  try {
140
- const result = await sdk.web3.resolveIPFSUrl(url, chainId);
150
+ const result = await web3.resolveIPFSUrl(url, chainId);
141
151
  return result;
142
152
  }
143
153
  catch (error) {
144
154
  console.error('Failed to resolve IPFS URL:', error);
145
155
  throw error;
146
156
  }
147
- }, [sdk, isInitialized]);
157
+ }, [web3, isInitialized]);
148
158
  const fetchAndProcessMetadata = useCallback(async (tokenUri, chainId) => {
149
- if (!isInitialized || !sdk) {
159
+ if (!isInitialized || !web3) {
150
160
  throw new Error('SDK not initialized. Call initialize() first.');
151
161
  }
152
162
  try {
153
- const result = await sdk.web3.fetchAndProcessMetadata(tokenUri, chainId);
163
+ const result = await web3.fetchAndProcessMetadata(tokenUri, chainId);
154
164
  return result;
155
165
  }
156
166
  catch (error) {
157
167
  console.error('Failed to fetch and process metadata:', error);
158
168
  throw error;
159
169
  }
160
- }, [sdk, isInitialized]);
170
+ }, [web3, isInitialized]);
161
171
  const getChainDataById = useCallback(async (chainId) => {
162
- if (!isInitialized || !sdk) {
172
+ if (!isInitialized || !web3) {
163
173
  throw new Error('SDK not initialized. Call initialize() first.');
164
174
  }
165
175
  try {
166
- const result = await sdk.web3.getChainDataById(chainId);
176
+ const result = await web3.getChainDataById(chainId);
167
177
  return result;
168
178
  }
169
179
  catch (error) {
170
180
  console.error('Failed to fetch chain data:', error);
171
181
  throw error;
172
182
  }
173
- }, [sdk, isInitialized]);
183
+ }, [web3, isInitialized]);
174
184
  const getExplorerUrl = useCallback(async (chainId, address, type) => {
175
- if (!isInitialized || !sdk) {
185
+ if (!isInitialized || !web3) {
176
186
  throw new Error('SDK not initialized. Call initialize() first.');
177
187
  }
178
188
  try {
179
- const result = await sdk.web3.getExplorerUrl(chainId, address, type);
189
+ const result = await web3.getExplorerUrl(chainId, address, type);
180
190
  return result;
181
191
  }
182
192
  catch (error) {
183
193
  console.error('Failed to generate explorer URL:', error);
184
194
  throw error;
185
195
  }
186
- }, [sdk, isInitialized]);
196
+ }, [web3, isInitialized]);
187
197
  // ==========================================
188
198
  // HELPER METHODS (delegating to core SDK)
189
199
  // ==========================================
@@ -203,9 +213,9 @@ export const useWeb3 = () => {
203
213
  * @see {@link getAccountOwnedTokensFromContract} - Recommended helper that handles this automatically
204
214
  */
205
215
  const extractTokenIds = useCallback((token) => {
206
- // Pure function - delegates to core SDK (no initialization required)
207
- return sdk?.web3.extractTokenIds(token);
208
- }, [sdk]);
216
+ // Pure function - delegates to Web3Manager (no initialization required)
217
+ return web3?.extractTokenIds(token);
218
+ }, [web3]);
209
219
  /**
210
220
  * Get owned tokens from a specific token contract for any blockchain address.
211
221
  *
@@ -240,11 +250,11 @@ export const useWeb3 = () => {
240
250
  * @see {@link buildCollectionRequest} - For manual request building
241
251
  */
242
252
  const getAccountOwnedTokensFromContract = useCallback(async (accountAddress, token, maxTokens = 50) => {
243
- if (!isInitialized || !sdk) {
253
+ if (!isInitialized || !web3) {
244
254
  throw new Error('SDK not initialized. Call initialize() first.');
245
255
  }
246
- return sdk.web3.getAccountOwnedTokensFromContract(accountAddress, token, maxTokens);
247
- }, [sdk, isInitialized]);
256
+ return web3.getAccountOwnedTokensFromContract(accountAddress, token, maxTokens);
257
+ }, [web3, isInitialized]);
248
258
  /**
249
259
  * Build a TokenCollectionRequest from a TokenDTO.
250
260
  *
@@ -258,11 +268,11 @@ export const useWeb3 = () => {
258
268
  * @returns TokenCollectionRequest ready for getTokenCollection()
259
269
  */
260
270
  const buildCollectionRequest = useCallback((accountAddress, token, maxTokens = 50) => {
261
- if (!sdk) {
271
+ if (!web3) {
262
272
  throw new Error('SDK not initialized. Call initialize() first.');
263
273
  }
264
- return sdk.web3.buildCollectionRequest(accountAddress, token, maxTokens);
265
- }, [sdk]);
274
+ return web3.buildCollectionRequest(accountAddress, token, maxTokens);
275
+ }, [web3]);
266
276
  return {
267
277
  getTokenBalance,
268
278
  getTokenMetadata,
@@ -275,6 +285,6 @@ export const useWeb3 = () => {
275
285
  extractTokenIds,
276
286
  getAccountOwnedTokensFromContract,
277
287
  buildCollectionRequest,
278
- isAvailable: isInitialized && !!sdk?.web3,
288
+ isAvailable: isInitialized && !!web3,
279
289
  };
280
290
  };
package/dist/index.d.ts CHANGED
@@ -206,9 +206,10 @@ export { PersSDKProvider, usePersSDK, type PersConfig, type PersSDKContext } fro
206
206
  * }
207
207
  * ```
208
208
  */
209
- export { useAuth, useTokens, useTransactions, useTransactionSigner, SigningStatus, useBusiness, useCampaigns, useRedemptions, useWeb3, usePurchases, useTenants, useUsers, useUserStatus, useFiles, useAnalytics, useDonations, useEvents } from './hooks';
209
+ export { useAuth, useTokens, useTokenBalances, useTransactions, useTransactionSigner, SigningStatus, useBusiness, useCampaigns, useRedemptions, useWeb3, usePurchases, useTenants, useUsers, useUserStatus, useFiles, useAnalytics, useDonations, useEvents } from './hooks';
210
210
  export type { OnStatusUpdateFn, StatusUpdateData, SigningStatusType } from './hooks';
211
211
  export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } from './hooks';
212
+ export type { TokenBalanceWithToken, UseTokenBalancesOptions, UseTokenBalancesResult } from './hooks';
212
213
  /**
213
214
  * React Native-optimized HTTP client with automatic request/response handling
214
215
  *
@@ -310,25 +311,95 @@ export type { TokenBalanceRequest, TokenBalance, TokenMetadata, TokenCollection,
310
311
  * @see {@link buildPOSBurnRequest} - Create POS burn requests (business submits burn on behalf of user)
311
312
  * @see {@link buildSubmissionRequest} - Create submission requests from QR/signature data
312
313
  */
313
- export { buildMintRequest, buildBurnRequest, buildTransferRequest, buildPOSTransferRequest, buildPOSBurnRequest, buildSubmissionRequest } from '@explorins/pers-sdk/transaction';
314
- export type { POSAuthorizationOptions } from '@explorins/pers-sdk/transaction';
314
+ export { buildMintRequest, buildBurnRequest, buildTransferRequest, buildPOSTransferRequest, buildPOSBurnRequest, buildSubmissionRequest, ClientTransactionType, extractDeadlineFromSigningData, buildPendingTransactionData } from '@explorins/pers-sdk/transaction';
315
+ export type { POSAuthorizationOptions, PendingTransactionParams } from '@explorins/pers-sdk/transaction';
315
316
  /**
316
- * SDK Error classes for type checking in catch blocks
317
+ * Structured error handling for PERS SDK
318
+ *
319
+ * The SDK provides comprehensive error classes and utilities for consistent error handling
320
+ * across all operations. Errors follow the StructuredError pattern from @explorins/pers-shared.
321
+ *
322
+ * **Error Classes:**
323
+ * - `PersApiError` - API errors with structured backend details
324
+ * - `AuthenticationError` - Authentication/authorization failures (401)
325
+ *
326
+ * **Error Utilities:**
327
+ * - `ErrorUtils.getMessage(error)` - Extract user-friendly message
328
+ * - `ErrorUtils.getStatus(error)` - Get HTTP status code
329
+ * - `ErrorUtils.isRetryable(error)` - Check if operation should be retried
330
+ * - `ErrorUtils.isTokenExpiredError(error)` - Detect token expiration
317
331
  *
318
332
  * @example
333
+ * **Basic Error Handling:**
319
334
  * ```typescript
320
- * import { PersApiError } from '@explorins/pers-sdk-react-native';
335
+ * import { PersApiError, ErrorUtils } from '@explorins/pers-sdk-react-native';
321
336
  *
322
337
  * try {
323
338
  * await sdk.campaigns.claimCampaign({ campaignId });
324
339
  * } catch (error) {
325
340
  * if (error instanceof PersApiError) {
326
- * console.log(error.message); // Clean backend message
327
- * console.log(error.code); // e.g., 'CAMPAIGN_BUSINESS_REQUIRED'
328
- * console.log(error.status); // e.g., 400
341
+ * // Structured error with backend details
342
+ * console.log('Error code:', error.code); // 'CAMPAIGN_BUSINESS_REQUIRED'
343
+ * console.log('Status:', error.status); // 400
344
+ * console.log('Message:', error.message); // Backend error message
345
+ * console.log('User message:', error.userMessage); // User-friendly message
346
+ * console.log('Retryable:', error.retryable); // false
347
+ * } else {
348
+ * // Generic error fallback
349
+ * const message = ErrorUtils.getMessage(error);
350
+ * console.error('Operation failed:', message);
329
351
  * }
330
352
  * }
331
353
  * ```
354
+ *
355
+ * @example
356
+ * **Error Utilities:**
357
+ * ```typescript
358
+ * import { ErrorUtils } from '@explorins/pers-sdk-react-native';
359
+ *
360
+ * try {
361
+ * await someOperation();
362
+ * } catch (error) {
363
+ * const status = ErrorUtils.getStatus(error); // Extract status code
364
+ * const message = ErrorUtils.getMessage(error); // Extract message
365
+ * const retryable = ErrorUtils.isRetryable(error); // Check if retryable
366
+ *
367
+ * if (ErrorUtils.isTokenExpiredError(error)) {
368
+ * // Handle token expiration
369
+ * await refreshToken();
370
+ * } else if (retryable) {
371
+ * // Retry operation
372
+ * await retry(someOperation);
373
+ * } else {
374
+ * // Show error to user
375
+ * showError(message);
376
+ * }
377
+ * }
378
+ * ```
379
+ *
380
+ * @example
381
+ * **React Native Error Display:**
382
+ * ```typescript
383
+ * import { PersApiError, ErrorUtils } from '@explorins/pers-sdk-react-native';
384
+ * import { Alert } from 'react-native';
385
+ *
386
+ * const handleError = (error: unknown) => {
387
+ * if (error instanceof PersApiError) {
388
+ * // Show structured error
389
+ * Alert.alert(
390
+ * 'Error',
391
+ * error.userMessage || error.message,
392
+ * [
393
+ * { text: 'OK' },
394
+ * error.retryable && { text: 'Retry', onPress: retry }
395
+ * ].filter(Boolean)
396
+ * );
397
+ * } else {
398
+ * // Show generic error
399
+ * Alert.alert('Error', ErrorUtils.getMessage(error));
400
+ * }
401
+ * };
402
+ * ```
332
403
  */
333
- export { PersApiError, AuthenticationError } from '@explorins/pers-sdk/core';
404
+ export { PersApiError, AuthenticationError, ErrorUtils } from '@explorins/pers-sdk/core';
334
405
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,aAAa,CAAC;AAMrB;;;;;;;;GAQG;AACH,OAAO,EACL,6BAA6B,EAC7B,KAAK,qBAAqB,EAC3B,MAAM,wCAAwC,CAAC;AAMhD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE;;;;;;;;GAQG;AACH,OAAO,EACL,wBAAwB,GACzB,MAAM,uCAAuC,CAAC;AAM/C;;;GAGG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EACL,eAAe,EACf,UAAU,EACV,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AAMrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AACH,OAAO,EACL,OAAO,EACP,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,EACd,OAAO,EACP,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAGrF,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAM7F;;;;;;GAMG;AACH,OAAO,EACL,qBAAqB,EACtB,MAAM,sCAAsC,CAAC;AAM9C;;;;;;;;GAQG;AACH,OAAO,EACL,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AAMrB;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,wBAAwB,CAAC;AAEvC;;;;GAIG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAE7E;;;;;GAKG;AACH,OAAO,EAEL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,iCAAiC,CAAC;AAEzC,YAAY,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAC;AAM/E;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,aAAa,CAAC;AAMrB;;;;;;;;GAQG;AACH,OAAO,EACL,6BAA6B,EAC7B,KAAK,qBAAqB,EAC3B,MAAM,wCAAwC,CAAC;AAMhD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE;;;;;;;;GAQG;AACH,OAAO,EACL,wBAAwB,GACzB,MAAM,uCAAuC,CAAC;AAM/C;;;GAGG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EACL,eAAe,EACf,UAAU,EACV,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AAMrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AACH,OAAO,EACL,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,EACd,OAAO,EACP,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,SAAS,EACV,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAGrF,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG7F,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAMtG;;;;;;GAMG;AACH,OAAO,EACL,qBAAqB,EACtB,MAAM,sCAAsC,CAAC;AAM9C;;;;;;;;GAQG;AACH,OAAO,EACL,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AAMrB;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,wBAAwB,CAAC;AAEvC;;;;GAIG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAE7E;;;;;GAKG;AACH,OAAO,EAEL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,2BAA2B,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,YAAY,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAMzG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACX,MAAM,0BAA0B,CAAC"}