@explorins/pers-sdk-react-native 1.5.34 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorins/pers-sdk-react-native",
3
- "version": "1.5.34",
3
+ "version": "1.5.35",
4
4
  "description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,7 +38,7 @@
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
40
  "@explorins/pers-sdk": "^1.6.42",
41
- "@explorins/pers-shared": "^2.1.52",
41
+ "@explorins/pers-shared": "^2.1.54",
42
42
  "@explorins/pers-signer": "^1.0.33",
43
43
  "@explorins/web3-ts": "^0.3.77",
44
44
  "buffer": "^6.0.3",
@@ -25,4 +25,5 @@ export type {
25
25
  StatusUpdateData,
26
26
  OnStatusUpdateFn,
27
27
  SigningStatus as SigningStatusType
28
- } from './useTransactionSigner';
28
+ } from './useTransactionSigner';
29
+ export type { UserOwnedTokensResult, Web3Hook } from './useWeb3';
@@ -8,6 +8,20 @@ import type {
8
8
  TokenMetadata
9
9
  } from '@explorins/pers-sdk/web3';
10
10
  import type { ChainData } from '@explorins/pers-sdk/web3-chain';
11
+ import type { TokenDTO } from '@explorins/pers-shared';
12
+ import { NativeTokenTypes } from '@explorins/pers-shared';
13
+
14
+ /**
15
+ * Result of getting user's owned tokens from a contract
16
+ */
17
+ export interface UserOwnedTokensResult {
18
+ /** The token definition (contains contract info, ABI, metadata definitions) */
19
+ token: TokenDTO;
20
+ /** Array of token balances the user owns (filtered to hasBalance: true) */
21
+ ownedTokens: readonly TokenBalance[];
22
+ /** Total count of owned tokens */
23
+ totalOwned: number;
24
+ }
11
25
 
12
26
  /**
13
27
  * React hook for Web3 operations in the PERS SDK
@@ -18,9 +32,48 @@ import type { ChainData } from '@explorins/pers-sdk/web3-chain';
18
32
  *
19
33
  * Note: Wallet addresses should be obtained from `user.wallets` via `usePersSDK()`.
20
34
  *
35
+ * ## ERC-1155 Token Handling
36
+ *
37
+ * **IMPORTANT**: ERC-1155 tokens require specific `tokenIds` to query balances.
38
+ * Unlike ERC-721, you cannot enumerate owned tokens - you must know which tokenId to check.
39
+ *
40
+ * The tokenIds come from `TokenDTO.metadata[].tokenMetadataIncrementalId`.
41
+ *
42
+ * ### Option 1: Use the helper method (Recommended)
43
+ * ```typescript
44
+ * const { getUserOwnedTokensFromContract } = useWeb3();
45
+ * const { getRewardTokens } = useTokens();
46
+ *
47
+ * const rewardTokens = await getRewardTokens();
48
+ * const result = await getUserOwnedTokensFromContract(walletAddress, rewardTokens[0]);
49
+ * console.log('Owned rewards:', result.ownedTokens);
50
+ * ```
51
+ *
52
+ * ### Option 2: Manual tokenIds extraction
53
+ * ```typescript
54
+ * const { getTokenCollection, extractTokenIds } = useWeb3();
55
+ * const { getRewardTokens } = useTokens();
56
+ *
57
+ * const rewardTokens = await getRewardTokens();
58
+ * const rewardToken = rewardTokens[0];
59
+ *
60
+ * // Extract tokenIds for ERC-1155
61
+ * const tokenIds = extractTokenIds(rewardToken);
62
+ *
63
+ * const collection = await getTokenCollection({
64
+ * accountAddress: walletAddress,
65
+ * contractAddress: rewardToken.contractAddress,
66
+ * abi: rewardToken.abi,
67
+ * chainId: rewardToken.chainId,
68
+ * tokenIds: tokenIds // Required for ERC-1155!
69
+ * });
70
+ *
71
+ * const ownedTokens = collection.tokens.filter(t => t.hasBalance);
72
+ * ```
73
+ *
21
74
  * @returns Web3 hook with methods for blockchain operations
22
75
  *
23
- * @example
76
+ * @example Basic Usage
24
77
  * ```typescript
25
78
  * function Web3Component() {
26
79
  * const { user } = usePersSDK();
@@ -146,6 +199,152 @@ export const useWeb3 = () => {
146
199
  }
147
200
  }, [sdk, isInitialized]);
148
201
 
202
+ /**
203
+ * Extract tokenIds from a TokenDTO for use with ERC-1155 contracts.
204
+ *
205
+ * ERC-1155 tokens require specific tokenIds to query balances. This helper
206
+ * extracts the `tokenMetadataIncrementalId` from each metadata entry.
207
+ *
208
+ * @param token - Token definition containing metadata array
209
+ * @returns Array of tokenId strings, or undefined if no metadata
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * const { extractTokenIds, getTokenCollection } = useWeb3();
214
+ * const { getRewardTokens } = useTokens();
215
+ *
216
+ * const rewardToken = (await getRewardTokens())[0];
217
+ * const tokenIds = extractTokenIds(rewardToken);
218
+ *
219
+ * if (tokenIds) {
220
+ * const collection = await getTokenCollection({
221
+ * accountAddress: walletAddress,
222
+ * contractAddress: rewardToken.contractAddress,
223
+ * abi: rewardToken.abi,
224
+ * chainId: rewardToken.chainId,
225
+ * tokenIds: tokenIds
226
+ * });
227
+ * }
228
+ * ```
229
+ */
230
+ const extractTokenIds = useCallback((token: TokenDTO): string[] | undefined => {
231
+ if (!token.metadata || token.metadata.length === 0) {
232
+ return undefined;
233
+ }
234
+ return token.metadata.map(meta => meta.tokenMetadataIncrementalId.toString());
235
+ }, []);
236
+
237
+ /**
238
+ * Get user's owned tokens from a specific token contract.
239
+ *
240
+ * This is a convenience method that automatically handles:
241
+ * - ERC-1155 tokenId extraction from metadata
242
+ * - Building the collection request
243
+ * - Filtering to only tokens with balance > 0
244
+ *
245
+ * **This is the recommended way to get user's owned reward/status tokens.**
246
+ *
247
+ * @param walletAddress - User's wallet address
248
+ * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
249
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
250
+ * @returns Promise resolving to result with owned tokens
251
+ * @throws Error if SDK is not initialized
252
+ *
253
+ * @example Get User's Owned Rewards
254
+ * ```typescript
255
+ * const { user } = usePersSDK();
256
+ * const { getRewardTokens } = useTokens();
257
+ * const { getUserOwnedTokensFromContract } = useWeb3();
258
+ *
259
+ * const walletAddress = user?.wallets?.[0]?.address;
260
+ * const rewardTokens = await getRewardTokens();
261
+ *
262
+ * for (const token of rewardTokens) {
263
+ * const result = await getUserOwnedTokensFromContract(walletAddress, token);
264
+ *
265
+ * console.log(`${token.name}: ${result.totalOwned} owned`);
266
+ * result.ownedTokens.forEach(owned => {
267
+ * console.log(` - TokenId ${owned.tokenId}: ${owned.balance}`);
268
+ * console.log(` Name: ${owned.metadata?.name}`);
269
+ * console.log(` Image: ${owned.metadata?.imageUrl}`);
270
+ * });
271
+ * }
272
+ * ```
273
+ */
274
+ const getUserOwnedTokensFromContract = useCallback(async (
275
+ walletAddress: string,
276
+ token: TokenDTO,
277
+ maxTokens: number = 50
278
+ ): Promise<UserOwnedTokensResult> => {
279
+ if (!isInitialized || !sdk) {
280
+ throw new Error('SDK not initialized. Call initialize() first.');
281
+ }
282
+
283
+ try {
284
+ // For ERC-1155, extract tokenIds from metadata
285
+ const tokenIds = token.type === NativeTokenTypes.ERC1155 ? extractTokenIds(token) : undefined;
286
+
287
+ const collection = await sdk.web3.getTokenCollection({
288
+ accountAddress: walletAddress,
289
+ contractAddress: token.contractAddress,
290
+ abi: token.abi,
291
+ chainId: token.chainId,
292
+ tokenIds,
293
+ maxTokens
294
+ });
295
+
296
+ // Filter to only owned tokens (hasBalance: true)
297
+ // For ERC721, include all since they're enumerated
298
+ const ownedTokens = token.type === NativeTokenTypes.ERC721
299
+ ? collection.tokens
300
+ : collection.tokens.filter(t => t.hasBalance);
301
+
302
+ return {
303
+ token,
304
+ ownedTokens,
305
+ totalOwned: ownedTokens.length
306
+ };
307
+ } catch (error) {
308
+ console.error('Failed to get user owned tokens:', error);
309
+ throw error;
310
+ }
311
+ }, [sdk, isInitialized, extractTokenIds]);
312
+
313
+ /**
314
+ * Build a TokenCollectionRequest from a TokenDTO.
315
+ *
316
+ * Automatically handles ERC-1155 tokenId extraction from metadata.
317
+ * Use this when you need more control over the request than
318
+ * `getUserOwnedTokensFromContract` provides.
319
+ *
320
+ * @param walletAddress - User's wallet address
321
+ * @param token - Token definition
322
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
323
+ * @returns TokenCollectionRequest ready for getTokenCollection()
324
+ *
325
+ * @example
326
+ * ```typescript
327
+ * const { buildCollectionRequest, getTokenCollection } = useWeb3();
328
+ *
329
+ * const request = buildCollectionRequest(walletAddress, rewardToken);
330
+ * const collection = await getTokenCollection(request);
331
+ * ```
332
+ */
333
+ const buildCollectionRequest = useCallback((
334
+ walletAddress: string,
335
+ token: TokenDTO,
336
+ maxTokens: number = 50
337
+ ): TokenCollectionRequest => {
338
+ return {
339
+ accountAddress: walletAddress,
340
+ contractAddress: token.contractAddress,
341
+ abi: token.abi,
342
+ chainId: token.chainId,
343
+ tokenIds: token.type === NativeTokenTypes.ERC1155 ? extractTokenIds(token) : undefined,
344
+ maxTokens
345
+ };
346
+ }, [extractTokenIds]);
347
+
149
348
  const resolveIPFSUrl = useCallback(async (url: string, chainId: number): Promise<string> => {
150
349
  if (!isInitialized || !sdk) {
151
350
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -203,6 +402,7 @@ export const useWeb3 = () => {
203
402
  }, [sdk, isInitialized]);
204
403
 
205
404
  return {
405
+ // Core methods
206
406
  getTokenBalance,
207
407
  getTokenMetadata,
208
408
  getTokenCollection,
@@ -210,6 +410,11 @@ export const useWeb3 = () => {
210
410
  fetchAndProcessMetadata,
211
411
  getChainDataById,
212
412
  getExplorerUrl,
413
+ // Helper methods for ERC-1155 tokens
414
+ extractTokenIds,
415
+ getUserOwnedTokensFromContract,
416
+ buildCollectionRequest,
417
+ // State
213
418
  isAvailable: isInitialized && !!sdk?.web3,
214
419
  };
215
420
  };