@explorins/pers-sdk-react-native 1.5.33 → 1.5.35

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/README.md CHANGED
@@ -176,17 +176,29 @@ function RewardScreen() {
176
176
  ```typescript
177
177
  // Authentication management
178
178
  const {
179
+ isInitialized,
179
180
  isAuthenticated,
180
181
  user,
181
- login,
182
- logout
182
+ login,
183
+ loginWithRawData,
184
+ logout,
185
+ refreshUserData,
186
+ getCurrentUser,
187
+ checkIsAuthenticated,
188
+ refreshTokens,
189
+ clearAuth,
190
+ hasValidAuth
183
191
  } = useAuth();
184
192
 
185
193
  // User profile operations
186
194
  const {
187
- getUserProfile,
188
- updateUserProfile,
189
- getUserPublicData
195
+ getCurrentUser,
196
+ updateCurrentUser,
197
+ getUserById,
198
+ getAllUsersPublic,
199
+ getAllUsers, // Admin
200
+ updateUser, // Admin
201
+ toggleUserStatus // Admin
190
202
  } = useUsers();
191
203
  ```
192
204
 
@@ -198,21 +210,30 @@ const {
198
210
  getTokens,
199
211
  getActiveCreditToken,
200
212
  getRewardTokens,
213
+ getTokenTypes,
214
+ getStatusTokens,
201
215
  getTokenByContract
202
216
  } = useTokens();
203
217
 
204
218
  // Transaction history
205
219
  const {
206
- getUserTransactionHistory,
220
+ createTransaction,
207
221
  getTransactionById,
208
- createTransaction
222
+ getUserTransactionHistory,
223
+ getTenantTransactions, // Admin
224
+ getPaginatedTransactions, // Admin
225
+ exportTransactionsCSV, // Admin
226
+ signingStatus, // UI feedback during blockchain signing
227
+ signingStatusMessage
209
228
  } = useTransactions();
210
229
 
211
230
  // Blockchain transaction signing
212
231
  const {
213
232
  signAndSubmitTransactionWithJWT,
214
233
  isSignerAvailable,
215
- isSignerInitialized
234
+ isSignerInitialized,
235
+ currentStatus,
236
+ statusMessage
216
237
  } = useTransactionSigner();
217
238
  ```
218
239
 
@@ -221,23 +242,42 @@ const {
221
242
  ```typescript
222
243
  // Business operations
223
244
  const {
224
- getBusinessProfile,
225
- updateBusinessProfile,
226
- getBusinessTypes
245
+ getActiveBusinesses,
246
+ getBusinessTypes,
247
+ getBusinesses,
248
+ getBusinessById,
249
+ getBusinessByAccount,
250
+ getBusinessesByType,
251
+ createBusiness, // Admin
252
+ updateBusiness, // Admin
253
+ toggleBusinessStatus // Admin
227
254
  } = useBusiness();
228
255
 
229
256
  // Campaign management
230
257
  const {
231
258
  getActiveCampaigns,
232
- participateInCampaign,
233
- claimCampaignReward
259
+ getCampaignById,
260
+ claimCampaign,
261
+ getUserClaims,
262
+ getCampaignTriggers,
263
+ getAllCampaigns, // Admin
264
+ getCampaignClaims, // Admin
265
+ getCampaignClaimsByUserId, // Admin
266
+ getCampaignClaimsByBusinessId // Admin
234
267
  } = useCampaigns();
235
268
 
236
269
  // Redemption system
237
270
  const {
238
- redeem,
271
+ getActiveRedemptions,
239
272
  getUserRedemptions,
240
- getActiveRedemptions
273
+ redeem,
274
+ getRedemptionTypes,
275
+ signingStatus, // UI feedback during blockchain signing
276
+ signingStatusMessage,
277
+ createRedemption, // Admin
278
+ getAllRedemptions, // Admin
279
+ updateRedemption, // Admin
280
+ toggleRedemptionStatus // Admin
241
281
  } = useRedemptions();
242
282
  ```
243
283
 
@@ -246,31 +286,54 @@ const {
246
286
  ```typescript
247
287
  // Purchase processing
248
288
  const {
249
- createPurchase,
250
- getUserPurchases,
251
- processPayment
289
+ createPaymentIntent,
290
+ getActivePurchaseTokens,
291
+ getAllUserPurchases
252
292
  } = usePurchases();
253
293
 
254
294
  // Multi-tenant support
255
295
  const {
256
- getTenantConfig,
257
- updateTenantConfig,
258
- getTenantAdmins
296
+ getTenantInfo,
297
+ getClientConfig,
298
+ getLoginToken,
299
+ getAdmins
259
300
  } = useTenants();
260
301
 
261
302
  // Analytics & reporting
262
303
  const {
263
- getTransactionAnalytics,
264
- getUserAnalytics,
265
- getBusinessAnalytics
304
+ getTransactionAnalytics
266
305
  } = useAnalytics();
267
306
 
268
- // Web3 & blockchain
307
+ // Web3 & blockchain (wallet addresses from user.wallets)
269
308
  const {
270
- getWalletBalance,
271
- createWallet,
272
- getTransactionHistory
309
+ getTokenBalance,
310
+ getTokenMetadata,
311
+ getTokenCollection,
312
+ resolveIPFSUrl,
313
+ fetchAndProcessMetadata,
314
+ getChainDataById,
315
+ getExplorerUrl
273
316
  } = useWeb3();
317
+
318
+ // User status & achievements
319
+ const {
320
+ getUserStatusTypes,
321
+ getEarnedUserStatus,
322
+ createUserStatusType // Admin
323
+ } = useUserStatus();
324
+
325
+ // File management
326
+ const {
327
+ getSignedPutUrl,
328
+ getSignedGetUrl,
329
+ getSignedUrl,
330
+ optimizeMedia
331
+ } = useFiles();
332
+
333
+ // Donations
334
+ const {
335
+ getDonationTypes
336
+ } = useDonations();
274
337
  ```
275
338
 
276
339
  ## EVM Blockchain Transaction Signing
@@ -455,25 +518,22 @@ function ErrorHandlingExample() {
455
518
  import { useAnalytics } from '@explorins/pers-sdk-react-native';
456
519
 
457
520
  function AnalyticsExample() {
458
- const {
459
- getTransactionAnalytics,
460
- getUserAnalytics,
461
- trackEvent
462
- } = useAnalytics();
521
+ const { getTransactionAnalytics } = useAnalytics();
463
522
 
464
523
  const loadAnalytics = async () => {
465
- const txAnalytics = await getTransactionAnalytics({
466
- dateRange: { start: '2023-01-01', end: '2023-12-31' }
467
- });
468
-
469
- const userAnalytics = await getUserAnalytics();
470
-
471
- // Track custom events
472
- await trackEvent('reward_claimed', {
473
- amount: 100,
474
- type: 'discount_voucher',
475
- timestamp: new Date().toISOString()
476
- });
524
+ try {
525
+ const txAnalytics = await getTransactionAnalytics({
526
+ groupBy: ['day'],
527
+ metrics: ['count', 'sum'],
528
+ startDate: '2023-01-01',
529
+ endDate: '2023-12-31'
530
+ });
531
+
532
+ console.log('Transaction analytics:', txAnalytics.results);
533
+ console.log('Execution time:', txAnalytics.metadata?.executionTime);
534
+ } catch (error) {
535
+ console.error('Failed to load analytics:', error);
536
+ }
477
537
  };
478
538
  }
479
539
  ```
@@ -15,4 +15,5 @@ export { useAnalytics } from './useAnalytics';
15
15
  export { useDonations } from './useDonations';
16
16
  export type { RawUserData } from './useAuth';
17
17
  export type { TransactionSignerHook, SubmissionResult, AuthenticatedUser, TransactionSigningResult, StatusUpdateData, OnStatusUpdateFn, SigningStatus as SigningStatusType } from './useTransactionSigner';
18
+ export type { UserOwnedTokensResult, Web3Hook } from './useWeb3';
18
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,qBAAqB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC"}
@@ -1,5 +1,17 @@
1
1
  import type { TokenBalance, TokenBalanceRequest, TokenCollectionRequest, TokenCollection, TokenMetadata } from '@explorins/pers-sdk/web3';
2
2
  import type { ChainData } from '@explorins/pers-sdk/web3-chain';
3
+ import type { TokenDTO } from '@explorins/pers-shared';
4
+ /**
5
+ * Result of getting user's owned tokens from a contract
6
+ */
7
+ export interface UserOwnedTokensResult {
8
+ /** The token definition (contains contract info, ABI, metadata definitions) */
9
+ token: TokenDTO;
10
+ /** Array of token balances the user owns (filtered to hasBalance: true) */
11
+ ownedTokens: readonly TokenBalance[];
12
+ /** Total count of owned tokens */
13
+ totalOwned: number;
14
+ }
3
15
  /**
4
16
  * React hook for Web3 operations in the PERS SDK
5
17
  *
@@ -9,9 +21,48 @@ import type { ChainData } from '@explorins/pers-sdk/web3-chain';
9
21
  *
10
22
  * Note: Wallet addresses should be obtained from `user.wallets` via `usePersSDK()`.
11
23
  *
24
+ * ## ERC-1155 Token Handling
25
+ *
26
+ * **IMPORTANT**: ERC-1155 tokens require specific `tokenIds` to query balances.
27
+ * Unlike ERC-721, you cannot enumerate owned tokens - you must know which tokenId to check.
28
+ *
29
+ * The tokenIds come from `TokenDTO.metadata[].tokenMetadataIncrementalId`.
30
+ *
31
+ * ### Option 1: Use the helper method (Recommended)
32
+ * ```typescript
33
+ * const { getUserOwnedTokensFromContract } = useWeb3();
34
+ * const { getRewardTokens } = useTokens();
35
+ *
36
+ * const rewardTokens = await getRewardTokens();
37
+ * const result = await getUserOwnedTokensFromContract(walletAddress, rewardTokens[0]);
38
+ * console.log('Owned rewards:', result.ownedTokens);
39
+ * ```
40
+ *
41
+ * ### Option 2: Manual tokenIds extraction
42
+ * ```typescript
43
+ * const { getTokenCollection, extractTokenIds } = useWeb3();
44
+ * const { getRewardTokens } = useTokens();
45
+ *
46
+ * const rewardTokens = await getRewardTokens();
47
+ * const rewardToken = rewardTokens[0];
48
+ *
49
+ * // Extract tokenIds for ERC-1155
50
+ * const tokenIds = extractTokenIds(rewardToken);
51
+ *
52
+ * const collection = await getTokenCollection({
53
+ * accountAddress: walletAddress,
54
+ * contractAddress: rewardToken.contractAddress,
55
+ * abi: rewardToken.abi,
56
+ * chainId: rewardToken.chainId,
57
+ * tokenIds: tokenIds // Required for ERC-1155!
58
+ * });
59
+ *
60
+ * const ownedTokens = collection.tokens.filter(t => t.hasBalance);
61
+ * ```
62
+ *
12
63
  * @returns Web3 hook with methods for blockchain operations
13
64
  *
14
- * @example
65
+ * @example Basic Usage
15
66
  * ```typescript
16
67
  * function Web3Component() {
17
68
  * const { user } = usePersSDK();
@@ -58,6 +109,9 @@ export declare const useWeb3: () => {
58
109
  fetchAndProcessMetadata: (tokenUri: string, chainId: number) => Promise<TokenMetadata | null>;
59
110
  getChainDataById: (chainId: number) => Promise<ChainData | null>;
60
111
  getExplorerUrl: (chainId: number, address: string, type: 'address' | 'tx') => Promise<string>;
112
+ extractTokenIds: (token: TokenDTO) => string[] | undefined;
113
+ getUserOwnedTokensFromContract: (walletAddress: string, token: TokenDTO, maxTokens?: number) => Promise<UserOwnedTokensResult>;
114
+ buildCollectionRequest: (walletAddress: string, token: TokenDTO, maxTokens?: number) => TokenCollectionRequest;
61
115
  isAvailable: boolean;
62
116
  };
63
117
  export type Web3Hook = ReturnType<typeof useWeb3>;
@@ -1 +1 @@
1
- {"version":3,"file":"useWeb3.d.ts","sourceRoot":"","sources":["../../src/hooks/useWeb3.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,aAAa,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AACH,eAAO,MAAM,OAAO;+BA0BkC,mBAAmB,KAAG,QAAQ,YAAY,CAAC;gCAiC1C,mBAAmB,KAAG,QAAQ,aAAa,GAAG,IAAI,CAAC;kCAcjD,sBAAsB,KAAG,QAAQ,eAAe,CAAC;0BAczD,MAAM,WAAW,MAAM,KAAG,QAAQ,MAAM,CAAC;wCAc3B,MAAM,WAAW,MAAM,KAAG,QAAQ,aAAa,GAAG,IAAI,CAAC;gCAc/D,MAAM,KAAG,QAAQ,SAAS,GAAG,IAAI,CAAC;8BAcpC,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG,IAAI,KAAG,QAAQ,MAAM,CAAC;;CAwBrH,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC"}
1
+ {"version":3,"file":"useWeb3.d.ts","sourceRoot":"","sources":["../../src/hooks/useWeb3.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,aAAa,EACd,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,KAAK,EAAE,QAAQ,CAAC;IAChB,2EAA2E;IAC3E,WAAW,EAAE,SAAS,YAAY,EAAE,CAAC;IACrC,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwFG;AACH,eAAO,MAAM,OAAO;+BA0BkC,mBAAmB,KAAG,QAAQ,YAAY,CAAC;gCAiC1C,mBAAmB,KAAG,QAAQ,aAAa,GAAG,IAAI,CAAC;kCAcjD,sBAAsB,KAAG,QAAQ,eAAe,CAAC;0BAgKzD,MAAM,WAAW,MAAM,KAAG,QAAQ,MAAM,CAAC;wCAc3B,MAAM,WAAW,MAAM,KAAG,QAAQ,aAAa,GAAG,IAAI,CAAC;gCAc/D,MAAM,KAAG,QAAQ,SAAS,GAAG,IAAI,CAAC;8BAcpC,MAAM,WAAW,MAAM,QAAQ,SAAS,GAAG,IAAI,KAAG,QAAQ,MAAM,CAAC;6BAhKxE,QAAQ,KAAG,MAAM,EAAE,GAAG,SAAS;oDA6C1D,MAAM,SACd,QAAQ,cACJ,MAAM,KAChB,QAAQ,qBAAqB,CAAC;4CAwDhB,MAAM,SACd,QAAQ,cACJ,MAAM,KAChB,sBAAsB;;CAmF1B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import { useCallback } from 'react';
2
2
  import { usePersSDK } from '../providers/PersSDKProvider';
3
+ import { NativeTokenTypes } from '@explorins/pers-shared';
3
4
  /**
4
5
  * React hook for Web3 operations in the PERS SDK
5
6
  *
@@ -9,9 +10,48 @@ import { usePersSDK } from '../providers/PersSDKProvider';
9
10
  *
10
11
  * Note: Wallet addresses should be obtained from `user.wallets` via `usePersSDK()`.
11
12
  *
13
+ * ## ERC-1155 Token Handling
14
+ *
15
+ * **IMPORTANT**: ERC-1155 tokens require specific `tokenIds` to query balances.
16
+ * Unlike ERC-721, you cannot enumerate owned tokens - you must know which tokenId to check.
17
+ *
18
+ * The tokenIds come from `TokenDTO.metadata[].tokenMetadataIncrementalId`.
19
+ *
20
+ * ### Option 1: Use the helper method (Recommended)
21
+ * ```typescript
22
+ * const { getUserOwnedTokensFromContract } = useWeb3();
23
+ * const { getRewardTokens } = useTokens();
24
+ *
25
+ * const rewardTokens = await getRewardTokens();
26
+ * const result = await getUserOwnedTokensFromContract(walletAddress, rewardTokens[0]);
27
+ * console.log('Owned rewards:', result.ownedTokens);
28
+ * ```
29
+ *
30
+ * ### Option 2: Manual tokenIds extraction
31
+ * ```typescript
32
+ * const { getTokenCollection, extractTokenIds } = useWeb3();
33
+ * const { getRewardTokens } = useTokens();
34
+ *
35
+ * const rewardTokens = await getRewardTokens();
36
+ * const rewardToken = rewardTokens[0];
37
+ *
38
+ * // Extract tokenIds for ERC-1155
39
+ * const tokenIds = extractTokenIds(rewardToken);
40
+ *
41
+ * const collection = await getTokenCollection({
42
+ * accountAddress: walletAddress,
43
+ * contractAddress: rewardToken.contractAddress,
44
+ * abi: rewardToken.abi,
45
+ * chainId: rewardToken.chainId,
46
+ * tokenIds: tokenIds // Required for ERC-1155!
47
+ * });
48
+ *
49
+ * const ownedTokens = collection.tokens.filter(t => t.hasBalance);
50
+ * ```
51
+ *
12
52
  * @returns Web3 hook with methods for blockchain operations
13
53
  *
14
- * @example
54
+ * @example Basic Usage
15
55
  * ```typescript
16
56
  * function Web3Component() {
17
57
  * const { user } = usePersSDK();
@@ -132,6 +172,138 @@ export const useWeb3 = () => {
132
172
  throw error;
133
173
  }
134
174
  }, [sdk, isInitialized]);
175
+ /**
176
+ * Extract tokenIds from a TokenDTO for use with ERC-1155 contracts.
177
+ *
178
+ * ERC-1155 tokens require specific tokenIds to query balances. This helper
179
+ * extracts the `tokenMetadataIncrementalId` from each metadata entry.
180
+ *
181
+ * @param token - Token definition containing metadata array
182
+ * @returns Array of tokenId strings, or undefined if no metadata
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * const { extractTokenIds, getTokenCollection } = useWeb3();
187
+ * const { getRewardTokens } = useTokens();
188
+ *
189
+ * const rewardToken = (await getRewardTokens())[0];
190
+ * const tokenIds = extractTokenIds(rewardToken);
191
+ *
192
+ * if (tokenIds) {
193
+ * const collection = await getTokenCollection({
194
+ * accountAddress: walletAddress,
195
+ * contractAddress: rewardToken.contractAddress,
196
+ * abi: rewardToken.abi,
197
+ * chainId: rewardToken.chainId,
198
+ * tokenIds: tokenIds
199
+ * });
200
+ * }
201
+ * ```
202
+ */
203
+ const extractTokenIds = useCallback((token) => {
204
+ if (!token.metadata || token.metadata.length === 0) {
205
+ return undefined;
206
+ }
207
+ return token.metadata.map(meta => meta.tokenMetadataIncrementalId.toString());
208
+ }, []);
209
+ /**
210
+ * Get user's owned tokens from a specific token contract.
211
+ *
212
+ * This is a convenience method that automatically handles:
213
+ * - ERC-1155 tokenId extraction from metadata
214
+ * - Building the collection request
215
+ * - Filtering to only tokens with balance > 0
216
+ *
217
+ * **This is the recommended way to get user's owned reward/status tokens.**
218
+ *
219
+ * @param walletAddress - User's wallet address
220
+ * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
221
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
222
+ * @returns Promise resolving to result with owned tokens
223
+ * @throws Error if SDK is not initialized
224
+ *
225
+ * @example Get User's Owned Rewards
226
+ * ```typescript
227
+ * const { user } = usePersSDK();
228
+ * const { getRewardTokens } = useTokens();
229
+ * const { getUserOwnedTokensFromContract } = useWeb3();
230
+ *
231
+ * const walletAddress = user?.wallets?.[0]?.address;
232
+ * const rewardTokens = await getRewardTokens();
233
+ *
234
+ * for (const token of rewardTokens) {
235
+ * const result = await getUserOwnedTokensFromContract(walletAddress, token);
236
+ *
237
+ * console.log(`${token.name}: ${result.totalOwned} owned`);
238
+ * result.ownedTokens.forEach(owned => {
239
+ * console.log(` - TokenId ${owned.tokenId}: ${owned.balance}`);
240
+ * console.log(` Name: ${owned.metadata?.name}`);
241
+ * console.log(` Image: ${owned.metadata?.imageUrl}`);
242
+ * });
243
+ * }
244
+ * ```
245
+ */
246
+ const getUserOwnedTokensFromContract = useCallback(async (walletAddress, token, maxTokens = 50) => {
247
+ if (!isInitialized || !sdk) {
248
+ throw new Error('SDK not initialized. Call initialize() first.');
249
+ }
250
+ try {
251
+ // For ERC-1155, extract tokenIds from metadata
252
+ const tokenIds = token.type === NativeTokenTypes.ERC1155 ? extractTokenIds(token) : undefined;
253
+ const collection = await sdk.web3.getTokenCollection({
254
+ accountAddress: walletAddress,
255
+ contractAddress: token.contractAddress,
256
+ abi: token.abi,
257
+ chainId: token.chainId,
258
+ tokenIds,
259
+ maxTokens
260
+ });
261
+ // Filter to only owned tokens (hasBalance: true)
262
+ // For ERC721, include all since they're enumerated
263
+ const ownedTokens = token.type === NativeTokenTypes.ERC721
264
+ ? collection.tokens
265
+ : collection.tokens.filter(t => t.hasBalance);
266
+ return {
267
+ token,
268
+ ownedTokens,
269
+ totalOwned: ownedTokens.length
270
+ };
271
+ }
272
+ catch (error) {
273
+ console.error('Failed to get user owned tokens:', error);
274
+ throw error;
275
+ }
276
+ }, [sdk, isInitialized, extractTokenIds]);
277
+ /**
278
+ * Build a TokenCollectionRequest from a TokenDTO.
279
+ *
280
+ * Automatically handles ERC-1155 tokenId extraction from metadata.
281
+ * Use this when you need more control over the request than
282
+ * `getUserOwnedTokensFromContract` provides.
283
+ *
284
+ * @param walletAddress - User's wallet address
285
+ * @param token - Token definition
286
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
287
+ * @returns TokenCollectionRequest ready for getTokenCollection()
288
+ *
289
+ * @example
290
+ * ```typescript
291
+ * const { buildCollectionRequest, getTokenCollection } = useWeb3();
292
+ *
293
+ * const request = buildCollectionRequest(walletAddress, rewardToken);
294
+ * const collection = await getTokenCollection(request);
295
+ * ```
296
+ */
297
+ const buildCollectionRequest = useCallback((walletAddress, token, maxTokens = 50) => {
298
+ return {
299
+ accountAddress: walletAddress,
300
+ contractAddress: token.contractAddress,
301
+ abi: token.abi,
302
+ chainId: token.chainId,
303
+ tokenIds: token.type === NativeTokenTypes.ERC1155 ? extractTokenIds(token) : undefined,
304
+ maxTokens
305
+ };
306
+ }, [extractTokenIds]);
135
307
  const resolveIPFSUrl = useCallback(async (url, chainId) => {
136
308
  if (!isInitialized || !sdk) {
137
309
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -185,6 +357,7 @@ export const useWeb3 = () => {
185
357
  }
186
358
  }, [sdk, isInitialized]);
187
359
  return {
360
+ // Core methods
188
361
  getTokenBalance,
189
362
  getTokenMetadata,
190
363
  getTokenCollection,
@@ -192,6 +365,11 @@ export const useWeb3 = () => {
192
365
  fetchAndProcessMetadata,
193
366
  getChainDataById,
194
367
  getExplorerUrl,
368
+ // Helper methods for ERC-1155 tokens
369
+ extractTokenIds,
370
+ getUserOwnedTokensFromContract,
371
+ buildCollectionRequest,
372
+ // State
195
373
  isAvailable: isInitialized && !!sdk?.web3,
196
374
  };
197
375
  };