@explorins/pers-sdk-react-native 2.1.5 → 2.1.6

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.
@@ -2,6 +2,15 @@ import React, { ReactNode } from 'react';
2
2
  import { PersSDK, PersConfig, DefaultAuthProvider } from '@explorins/pers-sdk/core';
3
3
  import { UserDTO, AdminDTO } from '@explorins/pers-shared';
4
4
  export type { PersConfig } from '@explorins/pers-sdk/core';
5
+ /**
6
+ * Context interface for PERS SDK React Native integration
7
+ *
8
+ * @property sdk - Main SDK instance (null until initialized)
9
+ * @property authProvider - Platform-specific auth provider
10
+ * @property isInitialized - Whether SDK has been initialized
11
+ * @property isAuthenticated - Whether user is currently authenticated
12
+ * @property user - Current user data (null if not authenticated)
13
+ */
5
14
  export interface PersSDKContext {
6
15
  sdk: PersSDK | null;
7
16
  authProvider: DefaultAuthProvider | null;
@@ -13,6 +22,35 @@ export interface PersSDKContext {
13
22
  refreshUserData: () => Promise<void>;
14
23
  restoreSession: () => Promise<UserDTO | null>;
15
24
  }
25
+ /**
26
+ * PERS SDK Provider for React Native
27
+ *
28
+ * Wraps your app to provide SDK context to all child components.
29
+ * Handles platform-specific initialization (DPoP, storage, etc.).
30
+ *
31
+ * @param config - SDK configuration (see PersConfig)
32
+ * @param config.apiProjectKey - Your PERS project key (required)
33
+ * @param config.environment - 'staging' | 'production' (default: 'staging')
34
+ * @param config.captureWalletEvents - Enable real-time blockchain events (default: true)
35
+ * @param config.dpop - DPoP configuration for enhanced security
36
+ *
37
+ * @example Basic usage
38
+ * ```tsx
39
+ * <PersSDKProvider config={{ apiProjectKey: 'my-project' }}>
40
+ * <App />
41
+ * </PersSDKProvider>
42
+ * ```
43
+ *
44
+ * @example Disable wallet events
45
+ * ```tsx
46
+ * <PersSDKProvider config={{
47
+ * apiProjectKey: 'my-project',
48
+ * captureWalletEvents: false // Disable auto-connect to blockchain events
49
+ * }}>
50
+ * <App />
51
+ * </PersSDKProvider>
52
+ * ```
53
+ */
16
54
  export declare const PersSDKProvider: React.FC<{
17
55
  children: ReactNode;
18
56
  config?: PersConfig;
@@ -1 +1 @@
1
- {"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAA2C,MAAM,OAAO,CAAC;AAEvH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAIpF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkB3D,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGzC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC/C;AAMD,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,CAwOA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
1
+ {"version":3,"file":"PersSDKProvider.d.ts","sourceRoot":"","sources":["../../src/providers/PersSDKProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAuC,SAAS,EAA2C,MAAM,OAAO,CAAC;AAEvH,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAIpF,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAkB3D,YAAY,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAE3D;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAE7B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAGpB,YAAY,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAGzC,aAAa,EAAE,OAAO,CAAC;IACvB,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC;IAGhC,UAAU,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClD,sBAAsB,EAAE,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,EAAE,eAAe,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5F,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;CAC/C;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC;IACrC,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,CAwOA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
@@ -7,7 +7,35 @@ import { createReactNativeAuthProvider } from './react-native-auth-provider';
7
7
  import { ReactNativeDPoPProvider } from './rn-dpop-provider';
8
8
  // Create the context
9
9
  const SDKContext = createContext(null);
10
- // Provider component
10
+ /**
11
+ * PERS SDK Provider for React Native
12
+ *
13
+ * Wraps your app to provide SDK context to all child components.
14
+ * Handles platform-specific initialization (DPoP, storage, etc.).
15
+ *
16
+ * @param config - SDK configuration (see PersConfig)
17
+ * @param config.apiProjectKey - Your PERS project key (required)
18
+ * @param config.environment - 'staging' | 'production' (default: 'staging')
19
+ * @param config.captureWalletEvents - Enable real-time blockchain events (default: true)
20
+ * @param config.dpop - DPoP configuration for enhanced security
21
+ *
22
+ * @example Basic usage
23
+ * ```tsx
24
+ * <PersSDKProvider config={{ apiProjectKey: 'my-project' }}>
25
+ * <App />
26
+ * </PersSDKProvider>
27
+ * ```
28
+ *
29
+ * @example Disable wallet events
30
+ * ```tsx
31
+ * <PersSDKProvider config={{
32
+ * apiProjectKey: 'my-project',
33
+ * captureWalletEvents: false // Disable auto-connect to blockchain events
34
+ * }}>
35
+ * <App />
36
+ * </PersSDKProvider>
37
+ * ```
38
+ */
11
39
  export const PersSDKProvider = ({ children, config }) => {
12
40
  const initializingRef = useRef(false);
13
41
  // State refs for stable functions to read current values
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorins/pers-sdk-react-native",
3
- "version": "2.1.5",
3
+ "version": "2.1.6",
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",
@@ -37,7 +37,7 @@
37
37
  "author": "eXplorins",
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@explorins/pers-sdk": "^2.1.6",
40
+ "@explorins/pers-sdk": "^2.1.14",
41
41
  "@explorins/pers-signer": "^1.0.33",
42
42
  "buffer": "^6.0.3",
43
43
  "ethers": "^6.15.0",
@@ -155,6 +155,7 @@
155
155
  "@ethersproject/scrypt": false
156
156
  },
157
157
  "devDependencies": {
158
+ "@explorins/pers-shared": "^2.1.117",
158
159
  "@rollup/plugin-commonjs": "^25.0.7",
159
160
  "@rollup/plugin-json": "^6.1.0",
160
161
  "@rollup/plugin-node-resolve": "^15.2.3",
@@ -35,23 +35,35 @@ export interface EventsHook {
35
35
  * React Native hook for PERS SDK event system
36
36
  *
37
37
  * This hook provides access to the platform-agnostic event system for subscribing to
38
- * transaction, authentication, campaign, and system events. All events include a
39
- * `userMessage` field ready for display to end users.
38
+ * transaction, authentication, campaign, blockchain, and system events. All events
39
+ * include a `userMessage` field ready for display to end users.
40
40
  *
41
41
  * **Event Domains:**
42
42
  * - `auth` - Authentication events (login, logout, token refresh)
43
43
  * - `user` - User profile events (update, create)
44
- * - `transaction` - Transaction events (created, completed, failed)
44
+ * - `transaction` - Transaction events (created, submitted, confirmed)
45
45
  * - `campaign` - Campaign events (claimed, activated)
46
46
  * - `redemption` - Redemption events (redeemed, expired)
47
47
  * - `business` - Business events (created, updated, membership)
48
+ * - `wallet` - Real-time blockchain events (Transfer, Approval, etc.) - Auto-enabled on auth
48
49
  * - `api` - API error events (network, validation, server errors)
49
50
  *
51
+ * **Blockchain Events (Wallet Domain):**
52
+ * When `sdk.connectWalletEvents()` is called (or auto-enabled via `captureWalletEvents: true`),
53
+ * real-time blockchain events are automatically routed through the same event system:
54
+ * ```typescript
55
+ * const { subscribe } = useEvents();
56
+ *
57
+ * subscribe((event) => {
58
+ * if (event.domain === 'wallet') {
59
+ * console.log('Blockchain event:', event.type); // wallet_transfer, wallet_approval, etc.
60
+ * }
61
+ * });
62
+ * ```
63
+ *
50
64
  * **Notification Levels:**
51
65
  * - `success` - Operation completed successfully
52
66
  * - `error` - Operation failed
53
- * - `warning` - Operation completed with warnings
54
- * - `info` - Informational event
55
67
  *
56
68
  * **Cleanup:**
57
69
  * All subscriptions created through this hook are automatically cleaned up when
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useState } from 'react';
1
+ import { useCallback, useEffect, useState, useRef } from 'react';
2
2
  import { usePersSDK } from '../providers/PersSDKProvider';
3
3
  import { useWeb3 } from './useWeb3';
4
4
  import { NativeTokenTypes, type TokenDTO } from '@explorins/pers-shared';
@@ -36,6 +36,18 @@ export interface UseTokenBalancesOptions {
36
36
  autoLoad?: boolean;
37
37
  /** Optional refresh interval in milliseconds (0 = disabled) */
38
38
  refreshInterval?: number;
39
+ /**
40
+ * Auto-refresh balances when wallet events are received (Transfer, Approval, etc.)
41
+ * Requires `captureWalletEvents: true` in SDK config (default)
42
+ * @default true
43
+ */
44
+ refreshOnWalletEvents?: boolean;
45
+ /**
46
+ * Debounce time for wallet event-triggered refreshes (milliseconds)
47
+ * Prevents rapid refresh calls during batch transfers
48
+ * @default 1000
49
+ */
50
+ walletEventDebounceMs?: number;
39
51
  }
40
52
 
41
53
  /**
@@ -126,6 +138,18 @@ export interface UseTokenBalancesResult {
126
138
  * ```
127
139
  *
128
140
  * @example
141
+ * **With Wallet Events (Real-time):**
142
+ * ```typescript
143
+ * // Auto-refresh on Transfer, Approval, and other blockchain events
144
+ * const { tokenBalances } = useTokenBalances({
145
+ * accountAddress: walletAddress!,
146
+ * availableTokens,
147
+ * refreshOnWalletEvents: true, // Enable real-time refresh (default: true)
148
+ * walletEventDebounceMs: 1000 // Debounce rapid events (default: 1000ms)
149
+ * });
150
+ * ```
151
+ *
152
+ * @example
129
153
  * **Multi-Wallet Support:**
130
154
  * ```typescript
131
155
  * function MultiWalletBalances() {
@@ -148,7 +172,9 @@ export function useTokenBalances(options: UseTokenBalancesOptions): UseTokenBala
148
172
  accountAddress,
149
173
  availableTokens = [],
150
174
  autoLoad = true,
151
- refreshInterval = 0
175
+ refreshInterval = 0,
176
+ refreshOnWalletEvents = true,
177
+ walletEventDebounceMs = 1000
152
178
  } = options;
153
179
 
154
180
  const { isAuthenticated, sdk } = usePersSDK();
@@ -157,6 +183,9 @@ export function useTokenBalances(options: UseTokenBalancesOptions): UseTokenBala
157
183
  const [tokenBalances, setTokenBalances] = useState<TokenBalanceWithToken[]>([]);
158
184
  const [isLoading, setIsLoading] = useState(false);
159
185
  const [error, setError] = useState<string | null>(null);
186
+
187
+ // Debounce ref for wallet events
188
+ const walletEventDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
160
189
 
161
190
  // Check if the hook is available for use
162
191
  const isAvailable = web3.isAvailable && isAuthenticated && !!accountAddress;
@@ -293,6 +322,35 @@ export function useTokenBalances(options: UseTokenBalancesOptions): UseTokenBala
293
322
  };
294
323
  }, [sdk, refreshInterval, isAvailable, loadBalances]);
295
324
 
325
+ // Wallet events refresh: listen for real-time blockchain events
326
+ // Refreshes on ANY wallet domain event (Transfer, TransferSingle, etc.)
327
+ // Debouncing prevents excessive API calls during rapid events
328
+ useEffect(() => {
329
+ if (!sdk || !refreshOnWalletEvents || !isAvailable) return;
330
+
331
+ const unsubscribe = sdk.events.subscribe((event) => {
332
+ if (event.domain === 'wallet') {
333
+ // Debounce rapid events (batch transfers, etc.)
334
+ if (walletEventDebounceRef.current) {
335
+ clearTimeout(walletEventDebounceRef.current);
336
+ }
337
+
338
+ walletEventDebounceRef.current = setTimeout(() => {
339
+ console.log(`[useTokenBalances] Wallet event (${event.type}), refreshing balances...`);
340
+ loadBalances();
341
+ walletEventDebounceRef.current = null;
342
+ }, walletEventDebounceMs);
343
+ }
344
+ }, { domains: ['wallet'] });
345
+
346
+ return () => {
347
+ unsubscribe();
348
+ if (walletEventDebounceRef.current) {
349
+ clearTimeout(walletEventDebounceRef.current);
350
+ }
351
+ };
352
+ }, [sdk, refreshOnWalletEvents, walletEventDebounceMs, isAvailable, loadBalances]);
353
+
296
354
  return {
297
355
  tokenBalances,
298
356
  isLoading,
@@ -1,12 +1,31 @@
1
1
  import { useCallback } from 'react';
2
2
  import { usePersSDK } from '../providers/PersSDKProvider';
3
3
  import type { UserDTO, UserCreateRequestDTO, PaginatedResponseDTO } from '@explorins/pers-shared';
4
- import type { UserPublicProfileDTO } from '@explorins/pers-sdk/user';
4
+ import type { UserPublicProfileDTO, UserQueryOptions } from '@explorins/pers-sdk/user';
5
+
6
+ // Re-export for consumers
7
+ export type { UserQueryOptions } from '@explorins/pers-sdk/user';
5
8
 
6
9
  export const useUsers = () => {
7
10
  const { sdk, isInitialized, isAuthenticated } = usePersSDK();
8
11
 
9
- const getCurrentUser = useCallback(async (): Promise<UserDTO> => {
12
+ /**
13
+ * Get the current authenticated user with optional include relations
14
+ *
15
+ * @param options - Query options including include relations
16
+ * @returns Current user data
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * // Basic
21
+ * const user = await getCurrentUser();
22
+ *
23
+ * // With wallets included
24
+ * const userWithWallets = await getCurrentUser({ include: ['wallets'] });
25
+ * console.log('Wallets:', userWithWallets.included?.wallets);
26
+ * ```
27
+ */
28
+ const getCurrentUser = useCallback(async (options?: UserQueryOptions): Promise<UserDTO> => {
10
29
  if (!isInitialized || !sdk) {
11
30
  throw new Error('SDK not initialized. Call initialize() first.');
12
31
  }
@@ -15,7 +34,7 @@ export const useUsers = () => {
15
34
  }
16
35
 
17
36
  try {
18
- const result = await sdk.users.getCurrentUser();
37
+ const result = await sdk.users.getCurrentUser(options);
19
38
  return result;
20
39
  } catch (error) {
21
40
  console.error('Failed to fetch current user:', error);
@@ -40,13 +59,29 @@ export const useUsers = () => {
40
59
  }
41
60
  }, [sdk, isInitialized, isAuthenticated]);
42
61
 
43
- const getUserById = useCallback(async (userId: string): Promise<UserDTO> => {
62
+ /**
63
+ * Get user by ID with optional include relations
64
+ *
65
+ * @param userId - User identifier (id, email, externalId, etc.)
66
+ * @param options - Query options including include relations
67
+ * @returns User data
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Basic
72
+ * const user = await getUserById('user-123');
73
+ *
74
+ * // With wallets included
75
+ * const userWithWallets = await getUserById('user-123', { include: ['wallets'] });
76
+ * ```
77
+ */
78
+ const getUserById = useCallback(async (userId: string, options?: UserQueryOptions): Promise<UserDTO> => {
44
79
  if (!isInitialized || !sdk) {
45
80
  throw new Error('SDK not initialized. Call initialize() first.');
46
81
  }
47
82
 
48
83
  try {
49
- const result = await sdk.users.getUserById(userId);
84
+ const result = await sdk.users.getUserById(userId, options);
50
85
  return result;
51
86
  } catch (error) {
52
87
  console.error('Failed to fetch user:', error);
@@ -97,16 +132,23 @@ export const useUsers = () => {
97
132
  }
98
133
  }, [sdk, isInitialized]);
99
134
 
100
- const toggleUserStatus = useCallback(async (user: UserDTO): Promise<UserDTO> => {
135
+ /**
136
+ * Toggle or set a user's active status (admin only)
137
+ *
138
+ * @param userId - User ID to update
139
+ * @param isActive - Optional explicit status. If omitted, toggles current status.
140
+ * @returns Updated user
141
+ */
142
+ const setUserActiveStatus = useCallback(async (userId: string, isActive?: boolean): Promise<UserDTO> => {
101
143
  if (!isInitialized || !sdk) {
102
144
  throw new Error('SDK not initialized. Call initialize() first.');
103
145
  }
104
146
 
105
147
  try {
106
- const result = await sdk.users.toggleUserStatus(user);
148
+ const result = await sdk.users.setUserActiveStatus(userId, isActive);
107
149
  return result;
108
150
  } catch (error) {
109
- console.error('Failed to toggle user status:', error);
151
+ console.error('Failed to set user active status:', error);
110
152
  throw error;
111
153
  }
112
154
  }, [sdk, isInitialized]);
@@ -118,7 +160,7 @@ export const useUsers = () => {
118
160
  getAllUsersPublic,
119
161
  getAllUsers,
120
162
  updateUser,
121
- toggleUserStatus,
163
+ setUserActiveStatus,
122
164
  isAvailable: isInitialized && !!sdk?.users,
123
165
  };
124
166
  };
@@ -9,8 +9,10 @@ import type {
9
9
  TokenMetadata,
10
10
  AccountOwnedTokensResult
11
11
  } from '@explorins/pers-sdk/web3';
12
- import type { ChainData } from '@explorins/pers-sdk/web3-chain';
13
- import type { TokenDTO } from '@explorins/pers-shared';
12
+ import type { TokenDTO } from '@explorins/pers-sdk/token';
13
+
14
+ // ChainData type - matches what Web3Manager.getChainDataById returns
15
+ type ChainData = Awaited<ReturnType<Web3Manager['getChainDataById']>>;
14
16
 
15
17
  // Re-export for convenience
16
18
  export type { AccountOwnedTokensResult } from '@explorins/pers-sdk/web3';
@@ -161,27 +163,40 @@ export const useWeb3 = () => {
161
163
  }
162
164
  }, [web3, isInitialized]);
163
165
 
164
- const resolveIPFSUrl = useCallback(async (url: string, chainId: number): Promise<string> => {
165
- if (!isInitialized || !web3) {
166
+ /**
167
+ * Resolve IPFS URL to HTTP gateway URL
168
+ *
169
+ * @deprecated Use `sdk.tenant.resolveIPFSUrl()` directly - IPFS is chain-agnostic
170
+ * @param url - IPFS URL to resolve (ipfs://...)
171
+ * @returns Promise resolving to HTTP gateway URL
172
+ */
173
+ const resolveIPFSUrl = useCallback(async (url: string): Promise<string> => {
174
+ if (!isInitialized || !sdk) {
166
175
  throw new Error('SDK not initialized. Call initialize() first.');
167
176
  }
168
177
 
169
178
  try {
170
- const result = await web3.resolveIPFSUrl(url, chainId);
179
+ const result = await sdk.tenants.resolveIPFSUrl(url);
171
180
  return result;
172
181
  } catch (error) {
173
182
  console.error('Failed to resolve IPFS URL:', error);
174
183
  throw error;
175
184
  }
176
- }, [web3, isInitialized]);
185
+ }, [sdk, isInitialized]);
177
186
 
178
- const fetchAndProcessMetadata = useCallback(async (tokenUri: string, chainId: number): Promise<TokenMetadata | null> => {
187
+ /**
188
+ * Fetch and process token metadata from a URI
189
+ *
190
+ * @param tokenUri - Token URI to fetch metadata from
191
+ * @returns Promise resolving to processed metadata or null
192
+ */
193
+ const fetchAndProcessMetadata = useCallback(async (tokenUri: string): Promise<TokenMetadata | null> => {
179
194
  if (!isInitialized || !web3) {
180
195
  throw new Error('SDK not initialized. Call initialize() first.');
181
196
  }
182
197
 
183
198
  try {
184
- const result = await web3.fetchAndProcessMetadata(tokenUri, chainId);
199
+ const result = await web3.fetchAndProcessMetadata(tokenUri);
185
200
  return result;
186
201
  } catch (error) {
187
202
  console.error('Failed to fetch and process metadata:', error);
@@ -189,7 +204,7 @@ export const useWeb3 = () => {
189
204
  }
190
205
  }, [web3, isInitialized]);
191
206
 
192
- const getChainDataById = useCallback(async (chainId: number): Promise<ChainData | null> => {
207
+ const getChainDataById = useCallback(async (chainId: number): Promise<ChainData> => {
193
208
  if (!isInitialized || !web3) {
194
209
  throw new Error('SDK not initialized. Call initialize() first.');
195
210
  }
@@ -255,7 +270,7 @@ export const useWeb3 = () => {
255
270
  *
256
271
  * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
257
272
  * @param token - Token definition (from getRewardTokens, getStatusTokens, etc.)
258
- * @param maxTokens - Maximum tokens to retrieve (default: 50)
273
+ * @param maxTokens - Maximum tokens to retrieve (default: 100, max: 100)
259
274
  * @returns Promise resolving to result with owned tokens
260
275
  * @throws Error if SDK is not initialized
261
276
  *
@@ -277,7 +292,7 @@ export const useWeb3 = () => {
277
292
  const getAccountOwnedTokensFromContract = useCallback(async (
278
293
  accountAddress: string,
279
294
  token: TokenDTO,
280
- maxTokens: number = 50
295
+ maxTokens: number = 100
281
296
  ): Promise<AccountOwnedTokensResult> => {
282
297
  if (!isInitialized || !web3) {
283
298
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -295,13 +310,13 @@ export const useWeb3 = () => {
295
310
  *
296
311
  * @param accountAddress - Any valid blockchain address (wallet, contract, etc.)
297
312
  * @param token - Token definition
298
- * @param maxTokens - Maximum tokens to retrieve (default: 50)
313
+ * @param maxTokens - Maximum tokens to retrieve (default: 100, max: 100)
299
314
  * @returns TokenCollectionRequest ready for getTokenCollection()
300
315
  */
301
316
  const buildCollectionRequest = useCallback((
302
317
  accountAddress: string,
303
318
  token: TokenDTO,
304
- maxTokens: number = 50
319
+ maxTokens: number = 100
305
320
  ): TokenCollectionRequest => {
306
321
  if (!web3) {
307
322
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -24,6 +24,15 @@ import type {
24
24
  // Re-export PersConfig for external use
25
25
  export type { PersConfig } from '@explorins/pers-sdk/core';
26
26
 
27
+ /**
28
+ * Context interface for PERS SDK React Native integration
29
+ *
30
+ * @property sdk - Main SDK instance (null until initialized)
31
+ * @property authProvider - Platform-specific auth provider
32
+ * @property isInitialized - Whether SDK has been initialized
33
+ * @property isAuthenticated - Whether user is currently authenticated
34
+ * @property user - Current user data (null if not authenticated)
35
+ */
27
36
  export interface PersSDKContext {
28
37
  // Main SDK instance
29
38
  sdk: PersSDK | null;
@@ -46,7 +55,35 @@ export interface PersSDKContext {
46
55
  // Create the context
47
56
  const SDKContext = createContext<PersSDKContext | null>(null);
48
57
 
49
- // Provider component
58
+ /**
59
+ * PERS SDK Provider for React Native
60
+ *
61
+ * Wraps your app to provide SDK context to all child components.
62
+ * Handles platform-specific initialization (DPoP, storage, etc.).
63
+ *
64
+ * @param config - SDK configuration (see PersConfig)
65
+ * @param config.apiProjectKey - Your PERS project key (required)
66
+ * @param config.environment - 'staging' | 'production' (default: 'staging')
67
+ * @param config.captureWalletEvents - Enable real-time blockchain events (default: true)
68
+ * @param config.dpop - DPoP configuration for enhanced security
69
+ *
70
+ * @example Basic usage
71
+ * ```tsx
72
+ * <PersSDKProvider config={{ apiProjectKey: 'my-project' }}>
73
+ * <App />
74
+ * </PersSDKProvider>
75
+ * ```
76
+ *
77
+ * @example Disable wallet events
78
+ * ```tsx
79
+ * <PersSDKProvider config={{
80
+ * apiProjectKey: 'my-project',
81
+ * captureWalletEvents: false // Disable auto-connect to blockchain events
82
+ * }}>
83
+ * <App />
84
+ * </PersSDKProvider>
85
+ * ```
86
+ */
50
87
  export const PersSDKProvider: React.FC<{
51
88
  children: ReactNode;
52
89
  config?: PersConfig;