@explorins/pers-sdk-react-native 1.5.34 → 1.5.36

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
@@ -51,19 +51,12 @@ npm install react-native-url-polyfill
51
51
 
52
52
  ## Critical Setup Requirement: Passkeys
53
53
 
54
- To enable Passkey authentication (WebAuthn) on iOS and Android, you **must** register your app's bundle information with the PERS backend.
54
+ To enable Passkey authentication (WebAuthn) on iOS and Android, you **must** complete the setup in **[REACT_NATIVE_PASSKEY_SETUP.md](./REACT_NATIVE_PASSKEY_SETUP.md)**.
55
55
 
56
- **Please send the following information to the PERS Team (support@explorins.com):**
57
-
58
- 1. **iOS Bundle Identifier**: e.g., `com.yourcompany.app`
59
- 2. **Apple Team ID**: Your 10-character Apple Team ID (e.g., `R553XYJPW7`)
60
- 3. **Android Package Name**: e.g., `com.yourcompany.app`
61
- 4. **Android SHA-256 Certificate Fingerprint**:
62
- * **Development**: The fingerprint from your local keystore or Expo development build.
63
- * **Production**: The fingerprint from your Google Play Console signing key.
64
-
65
- **Why is this required?**
66
- The PERS Signer server must host an `apple-app-site-association` file (for iOS) and an `assetlinks.json` file (for Android) that explicitly trusts your application. Without this, the operating system will reject Passkey creation requests.
56
+ This includes:
57
+ - Registering your app with the PERS backend (required for OS trust)
58
+ - Native configuration (Info.plist, AndroidManifest.xml)
59
+ - Expo/development build setup
67
60
 
68
61
  ## Quick Start
69
62
 
@@ -312,7 +305,11 @@ const {
312
305
  resolveIPFSUrl,
313
306
  fetchAndProcessMetadata,
314
307
  getChainDataById,
315
- getExplorerUrl
308
+ getExplorerUrl,
309
+ // Helper methods for token collections
310
+ extractTokenIds, // Extract tokenIds from TokenDTO metadata
311
+ getAccountOwnedTokensFromContract, // Recommended: Get owned tokens automatically
312
+ buildCollectionRequest // Build request for getTokenCollection
316
313
  } = useWeb3();
317
314
 
318
315
  // User status & achievements
@@ -336,6 +333,69 @@ const {
336
333
  } = useDonations();
337
334
  ```
338
335
 
336
+ ## Token Collection Helper Methods
337
+
338
+ The `useWeb3` hook includes helper methods for querying token balances from any blockchain address. These work with **all token standards** (ERC-20, ERC-721, ERC-1155).
339
+
340
+ ### Recommended: getAccountOwnedTokensFromContract
341
+
342
+ A unified API to get all tokens owned by any blockchain address:
343
+
344
+ ```typescript
345
+ import { useWeb3, useTokens, usePersSDK } from '@explorins/pers-sdk-react-native';
346
+
347
+ function RewardTokensScreen() {
348
+ const { user } = usePersSDK();
349
+ const { getRewardTokens } = useTokens();
350
+ const { getAccountOwnedTokensFromContract } = useWeb3();
351
+
352
+ const loadUserRewards = async () => {
353
+ const walletAddress = user?.wallets?.[0]?.address;
354
+ if (!walletAddress) return;
355
+
356
+ const rewardTokens = await getRewardTokens();
357
+
358
+ for (const token of rewardTokens) {
359
+ // Works with ERC-20, ERC-721, and ERC-1155 automatically
360
+ const result = await getAccountOwnedTokensFromContract(walletAddress, token);
361
+
362
+ console.log(`Token: ${token.symbol}`);
363
+ console.log(`Owned: ${result.totalOwned}`);
364
+
365
+ result.ownedTokens.forEach(owned => {
366
+ console.log(` - ${owned.metadata?.name}: ${owned.balance}`);
367
+ });
368
+ }
369
+ };
370
+
371
+ return (
372
+ <TouchableOpacity onPress={loadUserRewards}>
373
+ <Text>Load My Rewards</Text>
374
+ </TouchableOpacity>
375
+ );
376
+ }
377
+ ```
378
+
379
+ ### How It Handles Each Token Standard
380
+
381
+ | Token Type | What It Does |
382
+ |------------|--------------|
383
+ | **ERC-20** | Returns balance for fungible tokens |
384
+ | **ERC-721** | Enumerates all owned NFTs |
385
+ | **ERC-1155** | Extracts tokenIds from metadata, queries balances |
386
+
387
+ The helper abstracts away the complexity - especially for ERC-1155 which requires specific `tokenIds` that the helper extracts from `token.metadata[].tokenMetadataIncrementalId`.
388
+
389
+ ### Return Type
390
+
391
+ ```typescript
392
+ interface AccountOwnedTokensResult {
393
+ token: TokenDTO; // The token definition
394
+ ownedTokens: TokenBalance[]; // Tokens with balance > 0
395
+ totalOwned: number; // Count of owned tokens
396
+ }
397
+ ```
398
+
339
399
  ## EVM Blockchain Transaction Signing
340
400
 
341
401
  The `useTransactionSigner` hook provides secure EVM blockchain transaction signing:
@@ -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 { AccountOwnedTokensResult, 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,wBAAwB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC"}
@@ -1,5 +1,8 @@
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
+ import type { AccountOwnedTokensResult } from '@explorins/pers-sdk';
5
+ export type { AccountOwnedTokensResult } from '@explorins/pers-sdk';
3
6
  /**
4
7
  * React hook for Web3 operations in the PERS SDK
5
8
  *
@@ -58,6 +61,9 @@ export declare const useWeb3: () => {
58
61
  fetchAndProcessMetadata: (tokenUri: string, chainId: number) => Promise<TokenMetadata | null>;
59
62
  getChainDataById: (chainId: number) => Promise<ChainData | null>;
60
63
  getExplorerUrl: (chainId: number, address: string, type: 'address' | 'tx') => Promise<string>;
64
+ extractTokenIds: (token: TokenDTO) => string[] | undefined;
65
+ getAccountOwnedTokensFromContract: (accountAddress: string, token: TokenDTO, maxTokens?: number) => Promise<AccountOwnedTokensResult>;
66
+ buildCollectionRequest: (accountAddress: string, token: TokenDTO, maxTokens?: number) => TokenCollectionRequest;
61
67
  isAvailable: boolean;
62
68
  };
63
69
  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;AACvD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAGpE,YAAY,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;6BAiCxE,QAAQ,KAAG,MAAM,EAAE,GAAG,SAAS;wDAuCzD,MAAM,SACf,QAAQ,cACJ,MAAM,KAChB,QAAQ,wBAAwB,CAAC;6CAqBlB,MAAM,SACf,QAAQ,cACJ,MAAM,KAChB,sBAAsB;;CAqB1B,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC"}
@@ -184,6 +184,85 @@ export const useWeb3 = () => {
184
184
  throw error;
185
185
  }
186
186
  }, [sdk, isInitialized]);
187
+ // ==========================================
188
+ // HELPER METHODS (delegating to core SDK)
189
+ // ==========================================
190
+ /**
191
+ * Extract tokenIds from a TokenDTO's metadata.
192
+ *
193
+ * Extracts `tokenMetadataIncrementalId` from each metadata entry. This is
194
+ * particularly useful for ERC-1155 tokens which require specific tokenIds
195
+ * to query balances, but works with any token that has metadata.
196
+ *
197
+ * **Note:** For most use cases, prefer `getAccountOwnedTokensFromContract()`
198
+ * which handles tokenId extraction automatically.
199
+ *
200
+ * @param token - Token definition containing metadata array
201
+ * @returns Array of tokenId strings, or undefined if no metadata
202
+ *
203
+ * @see {@link getAccountOwnedTokensFromContract} - Recommended helper that handles this automatically
204
+ */
205
+ const extractTokenIds = useCallback((token) => {
206
+ // Pure function - delegates to core SDK (no initialization required)
207
+ return sdk?.web3.extractTokenIds(token);
208
+ }, [sdk]);
209
+ /**
210
+ * Get owned tokens from a specific token contract for any blockchain address.
211
+ *
212
+ * **Recommended method** for querying token balances. Automatically handles:
213
+ * - Token type detection (ERC-20, ERC-721, ERC-1155)
214
+ * - TokenId extraction from metadata (uses `extractTokenIds()` internally for ERC-1155)
215
+ * - Building the collection request
216
+ * - Filtering to only tokens with balance > 0
217
+ *
218
+ * Works with any valid blockchain address - can query user wallets, external
219
+ * wallets, contract addresses, or any other address holding tokens.
220
+ *
221
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
222
+ * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
223
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
224
+ * @returns Promise resolving to result with owned tokens
225
+ * @throws Error if SDK is not initialized
226
+ *
227
+ * @example Query user's wallet
228
+ * ```typescript
229
+ * const { user } = usePersSDK();
230
+ * const { getAccountOwnedTokensFromContract } = useWeb3();
231
+ * const { getRewardTokens } = useTokens();
232
+ *
233
+ * const userWallet = user?.wallets?.[0]?.address;
234
+ * const rewardTokens = await getRewardTokens();
235
+ * const result = await getAccountOwnedTokensFromContract(userWallet, rewardTokens[0]);
236
+ * console.log(`User owns ${result.totalOwned} tokens`);
237
+ * ```
238
+ *
239
+ * @see {@link extractTokenIds} - Low-level helper used internally for ERC-1155
240
+ * @see {@link buildCollectionRequest} - For manual request building
241
+ */
242
+ const getAccountOwnedTokensFromContract = useCallback(async (accountAddress, token, maxTokens = 50) => {
243
+ if (!isInitialized || !sdk) {
244
+ throw new Error('SDK not initialized. Call initialize() first.');
245
+ }
246
+ return sdk.web3.getAccountOwnedTokensFromContract(accountAddress, token, maxTokens);
247
+ }, [sdk, isInitialized]);
248
+ /**
249
+ * Build a TokenCollectionRequest from a TokenDTO.
250
+ *
251
+ * Automatically handles ERC-1155 tokenId extraction from metadata.
252
+ * Use this when you need more control over the request than
253
+ * `getAccountOwnedTokensFromContract` provides.
254
+ *
255
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
256
+ * @param token - Token definition
257
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
258
+ * @returns TokenCollectionRequest ready for getTokenCollection()
259
+ */
260
+ const buildCollectionRequest = useCallback((accountAddress, token, maxTokens = 50) => {
261
+ if (!sdk) {
262
+ throw new Error('SDK not initialized. Call initialize() first.');
263
+ }
264
+ return sdk.web3.buildCollectionRequest(accountAddress, token, maxTokens);
265
+ }, [sdk]);
187
266
  return {
188
267
  getTokenBalance,
189
268
  getTokenMetadata,
@@ -192,6 +271,10 @@ export const useWeb3 = () => {
192
271
  fetchAndProcessMetadata,
193
272
  getChainDataById,
194
273
  getExplorerUrl,
274
+ // Helper methods
275
+ extractTokenIds,
276
+ getAccountOwnedTokensFromContract,
277
+ buildCollectionRequest,
195
278
  isAvailable: isInitialized && !!sdk?.web3,
196
279
  };
197
280
  };
package/dist/index.js CHANGED
@@ -2629,6 +2629,8 @@ exports.ApiKeyType = void 0;
2629
2629
  ApiKeyType["ADMIN_JWT_REFRESH_TOKEN"] = "ADMIN_JWT_REFRESH_TOKEN";
2630
2630
  ApiKeyType["USER_JWT_ACCESS_TOKEN"] = "USER_JWT_ACCESS_TOKEN";
2631
2631
  ApiKeyType["USER_JWT_REFRESH_TOKEN"] = "USER_JWT_REFRESH_TOKEN";
2632
+ ApiKeyType["BUSINESS_JWT_ACCESS_TOKEN"] = "BUSINESS_JWT_ACCESS_TOKEN";
2633
+ ApiKeyType["BUSINESS_JWT_REFRESH_TOKEN"] = "BUSINESS_JWT_REFRESH_TOKEN";
2632
2634
  ApiKeyType["BLOCKCHAIN_WRITER_JWT"] = "BLOCKCHAIN_WRITER_JWT";
2633
2635
  ApiKeyType["BLOCKCHAIN_READER_JWT"] = "BLOCKCHAIN_READER_JWT";
2634
2636
  ApiKeyType["TRANSACTION_JWT_ACCESS_TOKEN"] = "TRANSACTION_JWT_ACCESS_TOKEN";
@@ -31675,6 +31677,37 @@ class DonationManager {
31675
31677
  *
31676
31678
  * Provides a simplified API for common Web3 blockchain tasks while maintaining
31677
31679
  * access to the full Web3 SDK for advanced use cases.
31680
+ *
31681
+ * ## Supported Token Standards
31682
+ *
31683
+ * - **ERC-20**: Fungible tokens (credits, points). Query balance with `getTokenBalance()`.
31684
+ * - **ERC-721**: Non-fungible tokens (unique NFTs). Supports enumeration - no tokenIds needed.
31685
+ * - **ERC-1155**: Multi-token standard (rewards, collectibles). Requires specific tokenIds.
31686
+ *
31687
+ * ## Recommended: Use Helper Methods
31688
+ *
31689
+ * For most use cases, use `getAccountOwnedTokensFromContract()` which automatically
31690
+ * handles token type detection and tokenId extraction:
31691
+ *
31692
+ * ```typescript
31693
+ * const result = await sdk.web3.getAccountOwnedTokensFromContract(walletAddress, token);
31694
+ * console.log(`Wallet owns ${result.totalOwned} tokens`);
31695
+ * ```
31696
+ *
31697
+ * ## Manual Approach (Advanced)
31698
+ *
31699
+ * For ERC-1155 tokens, tokenIds are extracted from `token.metadata[].tokenMetadataIncrementalId`:
31700
+ *
31701
+ * ```typescript
31702
+ * const tokenIds = token.metadata?.map(meta => meta.tokenMetadataIncrementalId.toString());
31703
+ * const collection = await sdk.web3.getTokenCollection({
31704
+ * accountAddress: walletAddress,
31705
+ * contractAddress: token.contractAddress,
31706
+ * abi: token.abi,
31707
+ * chainId: token.chainId,
31708
+ * tokenIds // Required for ERC-1155, optional for ERC-721
31709
+ * });
31710
+ * ```
31678
31711
  */
31679
31712
  class Web3Manager {
31680
31713
  constructor(apiClient) {
@@ -31762,6 +31795,132 @@ class Web3Manager {
31762
31795
  getWeb3ApplicationService() {
31763
31796
  return this.web3ApplicationService;
31764
31797
  }
31798
+ // ==========================================
31799
+ // HELPER METHODS
31800
+ // ==========================================
31801
+ /**
31802
+ * Extract tokenIds from a TokenDTO's metadata.
31803
+ *
31804
+ * Extracts `tokenMetadataIncrementalId` from each metadata entry. This is
31805
+ * particularly useful for ERC-1155 tokens which require specific tokenIds
31806
+ * to query balances, but works with any token that has metadata.
31807
+ *
31808
+ * **Note:** For most use cases, prefer `getAccountOwnedTokensFromContract()`
31809
+ * which handles tokenId extraction automatically.
31810
+ *
31811
+ * @param token - Token definition containing metadata array
31812
+ * @returns Array of tokenId strings, or undefined if no metadata
31813
+ *
31814
+ * @example Manual token collection request
31815
+ * ```typescript
31816
+ * const rewardToken = (await sdk.tokens.getRewardTokens())[0];
31817
+ * const tokenIds = sdk.web3.extractTokenIds(rewardToken);
31818
+ *
31819
+ * if (tokenIds) {
31820
+ * const collection = await sdk.web3.getTokenCollection({
31821
+ * accountAddress: walletAddress,
31822
+ * contractAddress: rewardToken.contractAddress,
31823
+ * abi: rewardToken.abi,
31824
+ * chainId: rewardToken.chainId,
31825
+ * tokenIds
31826
+ * });
31827
+ * }
31828
+ * ```
31829
+ *
31830
+ * @see {@link getAccountOwnedTokensFromContract} - Recommended helper that handles this automatically
31831
+ */
31832
+ extractTokenIds(token) {
31833
+ if (!token.metadata || token.metadata.length === 0) {
31834
+ return undefined;
31835
+ }
31836
+ return token.metadata.map(meta => meta.tokenMetadataIncrementalId.toString());
31837
+ }
31838
+ /**
31839
+ * Get owned tokens from a specific token contract for any blockchain address.
31840
+ *
31841
+ * **Recommended method** for querying token balances. Automatically handles:
31842
+ * - Token type detection (ERC-20, ERC-721, ERC-1155)
31843
+ * - TokenId extraction from metadata (uses `extractTokenIds()` internally for ERC-1155)
31844
+ * - Building the collection request
31845
+ * - Filtering to only tokens with balance > 0
31846
+ *
31847
+ * Works with any valid blockchain address - can query user wallets, external
31848
+ * wallets, contract addresses, or any other address holding tokens.
31849
+ *
31850
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
31851
+ * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
31852
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
31853
+ * @returns Promise resolving to collection result with owned tokens
31854
+ *
31855
+ * @example Query user's wallet
31856
+ * ```typescript
31857
+ * const userWallet = user.wallets[0].address;
31858
+ * const result = await sdk.web3.getAccountOwnedTokensFromContract(userWallet, rewardToken);
31859
+ * console.log(`User owns ${result.totalOwned} tokens`);
31860
+ * ```
31861
+ *
31862
+ * @example Query any external wallet
31863
+ * ```typescript
31864
+ * const externalWallet = '0x1234...abcd';
31865
+ * const result = await sdk.web3.getAccountOwnedTokensFromContract(externalWallet, rewardToken);
31866
+ * console.log(`Wallet owns ${result.totalOwned} tokens`);
31867
+ * ```
31868
+ *
31869
+ * @see {@link extractTokenIds} - Low-level helper used internally for ERC-1155
31870
+ * @see {@link buildCollectionRequest} - For manual request building
31871
+ */
31872
+ async getAccountOwnedTokensFromContract(accountAddress, token, maxTokens = 50) {
31873
+ // For ERC-1155, extract tokenIds from metadata
31874
+ const tokenIds = token.type === NativeTokenTypes.ERC1155 ? this.extractTokenIds(token) : undefined;
31875
+ const collection = await this.getTokenCollection({
31876
+ accountAddress: accountAddress,
31877
+ contractAddress: token.contractAddress,
31878
+ abi: token.abi,
31879
+ chainId: token.chainId,
31880
+ tokenIds,
31881
+ maxTokens
31882
+ });
31883
+ // Filter to only owned tokens (hasBalance: true)
31884
+ // For ERC721, include all since they're enumerated
31885
+ const ownedTokens = token.type === NativeTokenTypes.ERC721
31886
+ ? collection.tokens
31887
+ : collection.tokens.filter(t => t.hasBalance);
31888
+ return {
31889
+ token,
31890
+ ownedTokens,
31891
+ totalOwned: ownedTokens.length
31892
+ };
31893
+ }
31894
+ /**
31895
+ * Build a TokenCollectionRequest from a TokenDTO.
31896
+ *
31897
+ * Automatically handles ERC-1155 tokenId extraction from metadata.
31898
+ * Use this when you need more control over the request than
31899
+ * `getAccountOwnedTokensFromContract` provides.
31900
+ *
31901
+ * Works with any valid blockchain address - user wallets, external wallets, etc.
31902
+ *
31903
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
31904
+ * @param token - Token definition
31905
+ * @param maxTokens - Maximum tokens to retrieve
31906
+ * @returns TokenCollectionRequest ready for getTokenCollection()
31907
+ *
31908
+ * @example
31909
+ * ```typescript
31910
+ * const request = sdk.web3.buildCollectionRequest(walletAddress, rewardToken);
31911
+ * const collection = await sdk.web3.getTokenCollection(request);
31912
+ * ```
31913
+ */
31914
+ buildCollectionRequest(accountAddress, token, maxTokens = 50) {
31915
+ return {
31916
+ accountAddress: accountAddress,
31917
+ contractAddress: token.contractAddress,
31918
+ abi: token.abi,
31919
+ chainId: token.chainId,
31920
+ tokenIds: token.type === NativeTokenTypes.ERC1155 ? this.extractTokenIds(token) : undefined,
31921
+ maxTokens
31922
+ };
31923
+ }
31765
31924
  }
31766
31925
 
31767
31926
  /**
@@ -34629,6 +34788,85 @@ const useWeb3 = () => {
34629
34788
  throw error;
34630
34789
  }
34631
34790
  }, [sdk, isInitialized]);
34791
+ // ==========================================
34792
+ // HELPER METHODS (delegating to core SDK)
34793
+ // ==========================================
34794
+ /**
34795
+ * Extract tokenIds from a TokenDTO's metadata.
34796
+ *
34797
+ * Extracts `tokenMetadataIncrementalId` from each metadata entry. This is
34798
+ * particularly useful for ERC-1155 tokens which require specific tokenIds
34799
+ * to query balances, but works with any token that has metadata.
34800
+ *
34801
+ * **Note:** For most use cases, prefer `getAccountOwnedTokensFromContract()`
34802
+ * which handles tokenId extraction automatically.
34803
+ *
34804
+ * @param token - Token definition containing metadata array
34805
+ * @returns Array of tokenId strings, or undefined if no metadata
34806
+ *
34807
+ * @see {@link getAccountOwnedTokensFromContract} - Recommended helper that handles this automatically
34808
+ */
34809
+ const extractTokenIds = react.useCallback((token) => {
34810
+ // Pure function - delegates to core SDK (no initialization required)
34811
+ return sdk?.web3.extractTokenIds(token);
34812
+ }, [sdk]);
34813
+ /**
34814
+ * Get owned tokens from a specific token contract for any blockchain address.
34815
+ *
34816
+ * **Recommended method** for querying token balances. Automatically handles:
34817
+ * - Token type detection (ERC-20, ERC-721, ERC-1155)
34818
+ * - TokenId extraction from metadata (uses `extractTokenIds()` internally for ERC-1155)
34819
+ * - Building the collection request
34820
+ * - Filtering to only tokens with balance > 0
34821
+ *
34822
+ * Works with any valid blockchain address - can query user wallets, external
34823
+ * wallets, contract addresses, or any other address holding tokens.
34824
+ *
34825
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
34826
+ * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
34827
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
34828
+ * @returns Promise resolving to result with owned tokens
34829
+ * @throws Error if SDK is not initialized
34830
+ *
34831
+ * @example Query user's wallet
34832
+ * ```typescript
34833
+ * const { user } = usePersSDK();
34834
+ * const { getAccountOwnedTokensFromContract } = useWeb3();
34835
+ * const { getRewardTokens } = useTokens();
34836
+ *
34837
+ * const userWallet = user?.wallets?.[0]?.address;
34838
+ * const rewardTokens = await getRewardTokens();
34839
+ * const result = await getAccountOwnedTokensFromContract(userWallet, rewardTokens[0]);
34840
+ * console.log(`User owns ${result.totalOwned} tokens`);
34841
+ * ```
34842
+ *
34843
+ * @see {@link extractTokenIds} - Low-level helper used internally for ERC-1155
34844
+ * @see {@link buildCollectionRequest} - For manual request building
34845
+ */
34846
+ const getAccountOwnedTokensFromContract = react.useCallback(async (accountAddress, token, maxTokens = 50) => {
34847
+ if (!isInitialized || !sdk) {
34848
+ throw new Error('SDK not initialized. Call initialize() first.');
34849
+ }
34850
+ return sdk.web3.getAccountOwnedTokensFromContract(accountAddress, token, maxTokens);
34851
+ }, [sdk, isInitialized]);
34852
+ /**
34853
+ * Build a TokenCollectionRequest from a TokenDTO.
34854
+ *
34855
+ * Automatically handles ERC-1155 tokenId extraction from metadata.
34856
+ * Use this when you need more control over the request than
34857
+ * `getAccountOwnedTokensFromContract` provides.
34858
+ *
34859
+ * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
34860
+ * @param token - Token definition
34861
+ * @param maxTokens - Maximum tokens to retrieve (default: 50)
34862
+ * @returns TokenCollectionRequest ready for getTokenCollection()
34863
+ */
34864
+ const buildCollectionRequest = react.useCallback((accountAddress, token, maxTokens = 50) => {
34865
+ if (!sdk) {
34866
+ throw new Error('SDK not initialized. Call initialize() first.');
34867
+ }
34868
+ return sdk.web3.buildCollectionRequest(accountAddress, token, maxTokens);
34869
+ }, [sdk]);
34632
34870
  return {
34633
34871
  getTokenBalance,
34634
34872
  getTokenMetadata,
@@ -34637,6 +34875,10 @@ const useWeb3 = () => {
34637
34875
  fetchAndProcessMetadata,
34638
34876
  getChainDataById,
34639
34877
  getExplorerUrl,
34878
+ // Helper methods
34879
+ extractTokenIds,
34880
+ getAccountOwnedTokensFromContract,
34881
+ buildCollectionRequest,
34640
34882
  isAvailable: isInitialized && !!sdk?.web3,
34641
34883
  };
34642
34884
  };