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

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.
Files changed (72) hide show
  1. package/dist/hooks/index.d.ts +2 -2
  2. package/dist/hooks/index.d.ts.map +1 -1
  3. package/dist/hooks/index.js +1 -1
  4. package/dist/hooks/useAnalytics.d.ts.map +1 -1
  5. package/dist/hooks/useAnalytics.js +0 -1
  6. package/dist/hooks/useAuth.d.ts +0 -1
  7. package/dist/hooks/useAuth.d.ts.map +1 -1
  8. package/dist/hooks/useAuth.js +5 -18
  9. package/dist/hooks/useBusiness.d.ts.map +1 -1
  10. package/dist/hooks/useBusiness.js +0 -9
  11. package/dist/hooks/useCampaigns.d.ts.map +1 -1
  12. package/dist/hooks/useCampaigns.js +0 -10
  13. package/dist/hooks/useDonations.d.ts.map +1 -1
  14. package/dist/hooks/useDonations.js +0 -1
  15. package/dist/hooks/useFiles.d.ts.map +1 -1
  16. package/dist/hooks/useFiles.js +0 -4
  17. package/dist/hooks/usePurchases.d.ts.map +1 -1
  18. package/dist/hooks/usePurchases.js +0 -3
  19. package/dist/hooks/useRedemptions.d.ts +4 -1
  20. package/dist/hooks/useRedemptions.d.ts.map +1 -1
  21. package/dist/hooks/useRedemptions.js +6 -17
  22. package/dist/hooks/useTenants.d.ts.map +1 -1
  23. package/dist/hooks/useTenants.js +0 -3
  24. package/dist/hooks/useTokens.d.ts.map +1 -1
  25. package/dist/hooks/useTokens.js +0 -6
  26. package/dist/hooks/useTransactionSigner.d.ts +13 -1
  27. package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
  28. package/dist/hooks/useTransactionSigner.js +59 -2
  29. package/dist/hooks/useTransactions.d.ts +4 -1
  30. package/dist/hooks/useTransactions.d.ts.map +1 -1
  31. package/dist/hooks/useTransactions.js +9 -10
  32. package/dist/hooks/useUserStatus.d.ts.map +1 -1
  33. package/dist/hooks/useUserStatus.js +0 -3
  34. package/dist/hooks/useUsers.d.ts.map +1 -1
  35. package/dist/hooks/useUsers.js +0 -7
  36. package/dist/hooks/useWeb3.d.ts +26 -42
  37. package/dist/hooks/useWeb3.d.ts.map +1 -1
  38. package/dist/hooks/useWeb3.js +28 -54
  39. package/dist/index.d.ts +2 -1
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +509 -372
  42. package/dist/index.js.map +1 -1
  43. package/dist/providers/PersSDKProvider.d.ts +1 -3
  44. package/dist/providers/PersSDKProvider.d.ts.map +1 -1
  45. package/dist/providers/PersSDKProvider.js +13 -9
  46. package/dist/providers/rn-dpop-provider.d.ts +2 -4
  47. package/dist/providers/rn-dpop-provider.d.ts.map +1 -1
  48. package/dist/providers/rn-dpop-provider.js +50 -23
  49. package/dist/storage/rn-secure-storage.d.ts +1 -0
  50. package/dist/storage/rn-secure-storage.d.ts.map +1 -1
  51. package/dist/storage/rn-secure-storage.js +9 -12
  52. package/package.json +4 -4
  53. package/src/hooks/index.ts +10 -2
  54. package/src/hooks/useAnalytics.ts +0 -1
  55. package/src/hooks/useAuth.ts +4 -25
  56. package/src/hooks/useBusiness.ts +0 -9
  57. package/src/hooks/useCampaigns.ts +0 -10
  58. package/src/hooks/useDonations.ts +0 -1
  59. package/src/hooks/useFiles.ts +0 -4
  60. package/src/hooks/usePurchases.ts +0 -3
  61. package/src/hooks/useRedemptions.ts +7 -21
  62. package/src/hooks/useTenants.ts +0 -3
  63. package/src/hooks/useTokens.ts +0 -6
  64. package/src/hooks/useTransactionSigner.ts +74 -4
  65. package/src/hooks/useTransactions.ts +10 -12
  66. package/src/hooks/useUserStatus.ts +0 -3
  67. package/src/hooks/useUsers.ts +0 -7
  68. package/src/hooks/useWeb3.ts +29 -69
  69. package/src/index.ts +4 -0
  70. package/src/providers/PersSDKProvider.tsx +16 -17
  71. package/src/providers/rn-dpop-provider.ts +85 -45
  72. package/src/storage/rn-secure-storage.ts +13 -13
package/dist/index.js CHANGED
@@ -22507,21 +22507,115 @@ const getTokenOfOwnerByIndex = async (tokenContract, ownerAddress, index) => {
22507
22507
  };
22508
22508
 
22509
22509
  /**
22510
- * Clean an ABI to be compatible with Ethers.js
22511
- * Removes 'indexed' property from function inputs (only valid for events)
22510
+ * Clean input/output parameters for functions, constructors, errors
22511
+ * Removes properties that are invalid for non-event parameters
22512
+ */
22513
+ function cleanInputsOrOutputs(params) {
22514
+ if (!Array.isArray(params)) {
22515
+ return [];
22516
+ }
22517
+ return params.map((param) => {
22518
+ if (!param || typeof param !== 'object') {
22519
+ return param;
22520
+ }
22521
+ const cleanParam = {
22522
+ name: param.name ?? '',
22523
+ type: param.type ?? 'uint256', // Default to uint256 if type is missing (shouldn't happen)
22524
+ };
22525
+ // Handle tuple types with components
22526
+ if (param.components && Array.isArray(param.components)) {
22527
+ cleanParam.components = cleanInputsOrOutputs(param.components);
22528
+ }
22529
+ // Preserve internalType only if it doesn't cause issues
22530
+ // (some malformed internalTypes can break ethers)
22531
+ if (param.internalType && typeof param.internalType === 'string') {
22532
+ cleanParam.internalType = param.internalType;
22533
+ }
22534
+ // NOTE: 'indexed' is intentionally NOT included here
22535
+ // It's only valid for event parameters
22536
+ return cleanParam;
22537
+ });
22538
+ }
22539
+ /**
22540
+ * Clean an ABI to be compatible with Ethers.js v6
22541
+ * Handles common Web3.js ABI format incompatibilities:
22542
+ * - Removes 'indexed' from function inputs (only valid for event parameters)
22543
+ * - Removes 'indexed' from function outputs
22544
+ * - Removes 'internalType' if it causes parsing issues
22545
+ * - Ensures 'stateMutability' is valid
22546
+ * - Removes unknown/invalid properties that cause ethers to drop fragments
22512
22547
  */
22513
22548
  function cleanABI(abi) {
22514
22549
  return abi.map(fragment => {
22515
- if (fragment.type === 'function' && fragment.inputs) {
22516
- return {
22517
- ...fragment,
22518
- inputs: fragment.inputs.map((input) => {
22519
- const { indexed, ...cleanInput } = input;
22520
- return cleanInput;
22521
- })
22522
- };
22550
+ // Skip non-object fragments
22551
+ if (!fragment || typeof fragment !== 'object') {
22552
+ return fragment;
22523
22553
  }
22524
- return fragment;
22554
+ const cleanFragment = {
22555
+ type: fragment.type,
22556
+ name: fragment.name,
22557
+ };
22558
+ // Handle functions
22559
+ if (fragment.type === 'function') {
22560
+ // Clean inputs - remove 'indexed' (only valid for events)
22561
+ if (fragment.inputs) {
22562
+ cleanFragment.inputs = cleanInputsOrOutputs(fragment.inputs);
22563
+ }
22564
+ // Clean outputs - remove 'indexed'
22565
+ if (fragment.outputs) {
22566
+ cleanFragment.outputs = cleanInputsOrOutputs(fragment.outputs);
22567
+ }
22568
+ // Preserve valid function properties
22569
+ if (fragment.stateMutability) {
22570
+ cleanFragment.stateMutability = fragment.stateMutability;
22571
+ }
22572
+ // Handle legacy 'constant' and 'payable' for older ABIs
22573
+ if (fragment.constant !== undefined && !fragment.stateMutability) {
22574
+ cleanFragment.stateMutability = fragment.constant ? 'view' : 'nonpayable';
22575
+ }
22576
+ if (fragment.payable && !fragment.stateMutability) {
22577
+ cleanFragment.stateMutability = 'payable';
22578
+ }
22579
+ }
22580
+ // Handle events - 'indexed' IS valid here
22581
+ else if (fragment.type === 'event') {
22582
+ cleanFragment.anonymous = fragment.anonymous ?? false;
22583
+ if (fragment.inputs) {
22584
+ cleanFragment.inputs = fragment.inputs.map((input) => ({
22585
+ name: input.name ?? '',
22586
+ type: input.type,
22587
+ indexed: input.indexed ?? false,
22588
+ // Keep internalType for events if present
22589
+ ...(input.internalType && { internalType: input.internalType })
22590
+ }));
22591
+ }
22592
+ }
22593
+ // Handle constructor
22594
+ else if (fragment.type === 'constructor') {
22595
+ if (fragment.inputs) {
22596
+ cleanFragment.inputs = cleanInputsOrOutputs(fragment.inputs);
22597
+ }
22598
+ if (fragment.stateMutability) {
22599
+ cleanFragment.stateMutability = fragment.stateMutability;
22600
+ }
22601
+ }
22602
+ // Handle fallback/receive
22603
+ else if (fragment.type === 'fallback' || fragment.type === 'receive') {
22604
+ if (fragment.stateMutability) {
22605
+ cleanFragment.stateMutability = fragment.stateMutability;
22606
+ }
22607
+ }
22608
+ // Handle errors
22609
+ else if (fragment.type === 'error') {
22610
+ if (fragment.inputs) {
22611
+ cleanFragment.inputs = cleanInputsOrOutputs(fragment.inputs);
22612
+ }
22613
+ }
22614
+ // Pass through unknown types unchanged
22615
+ else {
22616
+ return fragment;
22617
+ }
22618
+ return cleanFragment;
22525
22619
  });
22526
22620
  }
22527
22621
  /**
@@ -22553,24 +22647,45 @@ function convertAbiToInterface(abi) {
22553
22647
  return abi;
22554
22648
  }
22555
22649
  // String format (JSON)
22650
+ let abiArray;
22556
22651
  if (typeof abi === 'string') {
22557
- const parsedAbi = JSON.parse(abi);
22558
- const cleanedAbi = Array.isArray(parsedAbi) ? cleanABI(parsedAbi) : parsedAbi;
22559
- return new Interface(cleanedAbi);
22652
+ abiArray = JSON.parse(abi);
22653
+ }
22654
+ else if (Array.isArray(abi)) {
22655
+ abiArray = abi;
22560
22656
  }
22561
- // Array or object format
22562
- if (Array.isArray(abi) || typeof abi === 'object') {
22563
- const cleanedAbi = Array.isArray(abi) ? cleanABI(abi) : abi;
22564
- return new Interface(cleanedAbi);
22657
+ else if (typeof abi === 'object') {
22658
+ // Single fragment object
22659
+ abiArray = [abi];
22565
22660
  }
22566
- throw new Error(`Unsupported ABI type: ${typeof abi}`);
22661
+ else {
22662
+ throw new Error(`Unsupported ABI type: ${typeof abi}`);
22663
+ }
22664
+ // Clean the ABI
22665
+ const cleanedAbi = cleanABI(abiArray);
22666
+ // Try to create Interface and validate all fragments were parsed
22667
+ const iface = new Interface(cleanedAbi);
22668
+ // Validation: Check if expected functions are present
22669
+ const expectedFunctions = cleanedAbi
22670
+ .filter((f) => f.type === 'function')
22671
+ .map((f) => f.name);
22672
+ const actualFunctions = iface.fragments
22673
+ .filter(f => f.type === 'function')
22674
+ .map(f => f.name);
22675
+ const droppedFunctions = expectedFunctions.filter((name) => !actualFunctions.includes(name));
22676
+ if (droppedFunctions.length > 0) {
22677
+ console.warn(`[web3-ts] Warning: ${droppedFunctions.length} function(s) were dropped during ABI conversion:`, droppedFunctions.join(', '));
22678
+ }
22679
+ return iface;
22567
22680
  }
22568
22681
  catch (error) {
22569
22682
  if (error.message.includes('JSON')) {
22570
22683
  throw new Error('Invalid JSON format in ABI string');
22571
22684
  }
22572
- if (error.message.includes('invalid fragment') || error.message.includes('parameter cannot be indexed')) {
22573
- throw new Error('Invalid ABI fragment structure - function inputs cannot be indexed');
22685
+ if (error.message.includes('invalid fragment') ||
22686
+ error.message.includes('parameter cannot be indexed')) {
22687
+ console.error('[web3-ts] ABI fragment error:', error.message);
22688
+ throw new Error(`Invalid ABI fragment structure: ${error.message}`);
22574
22689
  }
22575
22690
  throw error;
22576
22691
  }
@@ -23974,7 +24089,7 @@ class CampaignApi {
23974
24089
  * NEW: GET /trigger-sources
23975
24090
  */
23976
24091
  async getCampaignTriggers(options) {
23977
- let url = '/trigger-sources';
24092
+ let url = '/campaign-triggers';
23978
24093
  const params = [];
23979
24094
  if (options) {
23980
24095
  if (options.limit)
@@ -25402,6 +25517,17 @@ class IPFSInfrastructureApi {
25402
25517
  }
25403
25518
  return url;
25404
25519
  }
25520
+ /**
25521
+ * Fetch metadata from tokenURI, resolve all IPFS URLs, and normalize to SDK format.
25522
+ *
25523
+ * NORMALIZATION BOUNDARY: This is the single place where ERC metadata standard
25524
+ * (snake_case: image, animation_url) is converted to SDK format (camelCase: imageUrl, animationUrl).
25525
+ * All downstream consumers receive normalized SDK format with resolved HTTPS URLs.
25526
+ *
25527
+ * @param tokenUri - Token URI (can be ipfs:// or https://)
25528
+ * @param chainId - Chain ID for IPFS gateway selection
25529
+ * @returns Normalized TokenMetadata with resolved HTTPS URLs, or null on error
25530
+ */
25405
25531
  async fetchAndProcessMetadata(tokenUri, chainId) {
25406
25532
  try {
25407
25533
  const resolvedUri = await this.resolveIPFSUrl(tokenUri, chainId);
@@ -25409,15 +25535,25 @@ class IPFSInfrastructureApi {
25409
25535
  if (!response.ok) {
25410
25536
  throw new Error(`HTTP error! status: ${response.status}`);
25411
25537
  }
25412
- const metadata = await response.json();
25413
- // Process and return clean metadata
25538
+ const rawMetadata = await response.json();
25539
+ // Resolve IPFS URLs for media fields
25540
+ const resolvedImageUrl = rawMetadata.image
25541
+ ? await this.resolveIPFSUrl(rawMetadata.image, chainId)
25542
+ : '';
25543
+ const resolvedAnimationUrl = rawMetadata.animation_url
25544
+ ? await this.resolveIPFSUrl(rawMetadata.animation_url, chainId)
25545
+ : undefined;
25546
+ // Extract custom properties (anything not in ERC standard)
25547
+ const customProperties = Object.fromEntries(Object.entries(rawMetadata).filter(([key]) => !['name', 'description', 'image', 'animation_url', 'external_url', 'attributes'].includes(key)));
25548
+ // Return normalized SDK format (typed as TokenMetadata)
25414
25549
  return {
25415
- name: metadata.name || '',
25416
- description: metadata.description || '',
25417
- image: metadata.image ? await this.resolveIPFSUrl(metadata.image, chainId) : '',
25418
- attributes: metadata.attributes || [],
25419
- animation_url: metadata.animation_url ? await this.resolveIPFSUrl(metadata.animation_url, chainId) : undefined,
25420
- external_url: metadata.external_url || undefined
25550
+ name: rawMetadata.name || '',
25551
+ description: rawMetadata.description || '',
25552
+ imageUrl: resolvedImageUrl,
25553
+ animationUrl: resolvedAnimationUrl,
25554
+ externalUrl: rawMetadata.external_url || undefined,
25555
+ attributes: rawMetadata.attributes || [],
25556
+ ...customProperties
25421
25557
  };
25422
25558
  }
25423
25559
  catch (error) {
@@ -25701,8 +25837,8 @@ class MetadataDomainService {
25701
25837
  class ContractDomainService {
25702
25838
  constructor() { }
25703
25839
  analyzeContract(abi) {
25704
- abi = convertAbiToInterface(abi);
25705
- const methods = abi.fragments.filter(item => item.type === 'function').map(item => item.name);
25840
+ const cleanAbi = convertAbiToInterface(abi);
25841
+ const methods = cleanAbi.fragments.filter(item => item.type === 'function').map(item => item.name);
25706
25842
  // ERC-721 detection
25707
25843
  const hasOwnerOf = methods.includes('ownerOf');
25708
25844
  const hasTokenURI = methods.includes('tokenURI');
@@ -25733,28 +25869,6 @@ class ContractDomainService {
25733
25869
  */
25734
25870
  class Web3ApplicationService {
25735
25871
  constructor(web3Api, ipfsApi) {
25736
- // Type-safe metadata conversion methods for ERC-721/ERC-1155 standards
25737
- this.metadataMapper = {
25738
- fromERCStandard: (ercMetadata) => ({
25739
- name: ercMetadata.name || '',
25740
- description: ercMetadata.description || '',
25741
- imageUrl: ercMetadata.image || '',
25742
- externalUrl: ercMetadata.external_url,
25743
- animationUrl: ercMetadata.animation_url,
25744
- animationUrlConverted: undefined, // Will be set by IPFS conversion
25745
- attributes: ercMetadata.attributes || [],
25746
- ...ercMetadata
25747
- }),
25748
- toERCStandard: (metadata) => ({
25749
- name: metadata.name,
25750
- description: metadata.description,
25751
- image: metadata.imageUrl,
25752
- animation_url: metadata.animationUrl,
25753
- external_url: metadata.externalUrl,
25754
- attributes: metadata.attributes,
25755
- ...Object.fromEntries(Object.entries(metadata).filter(([key]) => !['name', 'description', 'imageUrl', 'animationUrl', 'externalUrl', 'attributes', 'animationUrlConverted'].includes(key)))
25756
- })
25757
- };
25758
25872
  // Create domain services with injected infrastructure dependencies
25759
25873
  this.contractDomainService = new ContractDomainService();
25760
25874
  this.metadataDomainService = new MetadataDomainService(ipfsApi);
@@ -25773,7 +25887,15 @@ class Web3ApplicationService {
25773
25887
  });
25774
25888
  }
25775
25889
  /**
25776
- * Get metadata for a specific token from on-chain
25890
+ * Get metadata for a specific token from on-chain.
25891
+ *
25892
+ * Returns metadata with:
25893
+ * - Normalized property names (imageUrl, animationUrl - SDK standard)
25894
+ * - All IPFS URLs already resolved to HTTPS
25895
+ * - Custom properties preserved from original metadata
25896
+ *
25897
+ * Note: Normalization happens at infrastructure layer (IPFS API),
25898
+ * so no additional transformation needed here.
25777
25899
  */
25778
25900
  async getTokenMetadata(request) {
25779
25901
  const domainResult = await this.tokenDomainService.getTokenMetadata({
@@ -25782,6 +25904,7 @@ class Web3ApplicationService {
25782
25904
  tokenId: request.tokenId || '',
25783
25905
  chainId: request.chainId
25784
25906
  });
25907
+ // Metadata is already normalized at infrastructure layer
25785
25908
  return domainResult.metadata;
25786
25909
  }
25787
25910
  /**
@@ -25804,22 +25927,13 @@ class Web3ApplicationService {
25804
25927
  return this.metadataDomainService.resolveIPFSUrl(url, chainId);
25805
25928
  }
25806
25929
  /**
25807
- * Fetch and process metadata from URI with IPFS conversion
25930
+ * Fetch and process metadata from any URI with IPFS conversion.
25931
+ *
25932
+ * Use this for ad-hoc metadata fetching when you have a tokenURI.
25933
+ * Normalization happens at infrastructure layer.
25808
25934
  */
25809
25935
  async fetchAndProcessMetadata(tokenUri, chainId) {
25810
- const domainMetadata = await this.metadataDomainService.fetchAndProcessMetadata(tokenUri, chainId);
25811
- if (!domainMetadata)
25812
- return null;
25813
- // Convert from ERC token standard to our clean interface
25814
- const cleanMetadata = this.metadataMapper.fromERCStandard(domainMetadata);
25815
- // Add IPFS conversion if needed
25816
- if (cleanMetadata.animationUrl?.startsWith('ipfs://')) {
25817
- return {
25818
- ...cleanMetadata,
25819
- animationUrlConverted: await this.resolveIPFSUrl(cleanMetadata.animationUrl, chainId)
25820
- };
25821
- }
25822
- return cleanMetadata;
25936
+ return this.metadataDomainService.fetchAndProcessMetadata(tokenUri, chainId);
25823
25937
  }
25824
25938
  }
25825
25939
 
@@ -32044,6 +32158,119 @@ class PersSDK {
32044
32158
  }
32045
32159
  }
32046
32160
 
32161
+ /**
32162
+ * AsyncStorage Token Storage for React Native Mobile Platforms
32163
+ *
32164
+ * Bundler-agnostic AsyncStorage implementation for mobile platforms
32165
+ */
32166
+ /**
32167
+ * Bundler-agnostic AsyncStorage wrapper
32168
+ * Handles different module resolution patterns across bundlers (Metro, Webpack, Rollup, etc.)
32169
+ */
32170
+ class BundlerAgnosticAsyncStorage {
32171
+ constructor(asyncStorageModule) {
32172
+ // Try different import patterns to handle various bundlers
32173
+ if (asyncStorageModule?.default?.getItem) {
32174
+ // Metro/Webpack pattern: { default: { getItem, setItem, ... } }
32175
+ this.storage = asyncStorageModule.default;
32176
+ }
32177
+ else if (asyncStorageModule?.getItem) {
32178
+ // Direct export pattern: { getItem, setItem, ... }
32179
+ this.storage = asyncStorageModule;
32180
+ }
32181
+ else if (typeof asyncStorageModule === 'function') {
32182
+ // Function export pattern (some bundlers)
32183
+ this.storage = asyncStorageModule();
32184
+ }
32185
+ else {
32186
+ // Log the structure for debugging
32187
+ console.error('[BundlerAgnosticAsyncStorage] Unknown AsyncStorage structure:', asyncStorageModule);
32188
+ throw new Error('AsyncStorage methods not found. Expected structure with getItem/setItem methods. ' +
32189
+ 'Make sure @react-native-async-storage/async-storage is properly installed.');
32190
+ }
32191
+ // Validate that we have the required methods
32192
+ const requiredMethods = ['getItem', 'setItem', 'removeItem', 'getAllKeys', 'multiRemove'];
32193
+ const missingMethods = requiredMethods.filter(method => typeof this.storage[method] !== 'function');
32194
+ if (missingMethods.length > 0) {
32195
+ throw new Error(`AsyncStorage missing required methods: ${missingMethods.join(', ')}. ` +
32196
+ 'Ensure @react-native-async-storage/async-storage is properly installed and compatible.');
32197
+ }
32198
+ }
32199
+ async getItem(key) {
32200
+ return this.storage.getItem(key);
32201
+ }
32202
+ async setItem(key, value) {
32203
+ return this.storage.setItem(key, value);
32204
+ }
32205
+ async removeItem(key) {
32206
+ return this.storage.removeItem(key);
32207
+ }
32208
+ async getAllKeys() {
32209
+ return this.storage.getAllKeys();
32210
+ }
32211
+ async multiRemove(keys) {
32212
+ return this.storage.multiRemove(keys);
32213
+ }
32214
+ }
32215
+ /**
32216
+ * AsyncStorage implementation for mobile platforms
32217
+ *
32218
+ * This class is only used on mobile platforms (iOS/Android).
32219
+ * Web platforms use LocalStorageTokenStorage from core SDK.
32220
+ */
32221
+ class AsyncStorageTokenStorage {
32222
+ constructor(keyPrefix = 'pers_tokens_') {
32223
+ this.keyPrefix = keyPrefix;
32224
+ try {
32225
+ // Initialize bundler-agnostic AsyncStorage wrapper
32226
+ this.asyncStorage = new BundlerAgnosticAsyncStorage(AsyncStorage);
32227
+ }
32228
+ catch (error) {
32229
+ console.error('[AsyncStorageTokenStorage] Failed to initialize:', error);
32230
+ throw new Error('Failed to initialize AsyncStorage. Make sure @react-native-async-storage/async-storage is installed and ' +
32231
+ 'this code is running on a React Native mobile platform (not web).');
32232
+ }
32233
+ }
32234
+ async set(key, value) {
32235
+ try {
32236
+ await this.asyncStorage.setItem(`${this.keyPrefix}${key}`, value);
32237
+ }
32238
+ catch (error) {
32239
+ console.error(`Failed to store token ${key}:`, error);
32240
+ throw new Error(`Token storage failed: ${error}`);
32241
+ }
32242
+ }
32243
+ async get(key) {
32244
+ try {
32245
+ return await this.asyncStorage.getItem(`${this.keyPrefix}${key}`);
32246
+ }
32247
+ catch (error) {
32248
+ console.error(`Failed to retrieve token ${key}:`, error);
32249
+ return null;
32250
+ }
32251
+ }
32252
+ async remove(key) {
32253
+ try {
32254
+ await this.asyncStorage.removeItem(`${this.keyPrefix}${key}`);
32255
+ }
32256
+ catch (error) {
32257
+ console.error(`Failed to remove token ${key}:`, error);
32258
+ }
32259
+ }
32260
+ async clear() {
32261
+ try {
32262
+ const allKeys = await this.asyncStorage.getAllKeys();
32263
+ const ourKeys = allKeys.filter(key => key.startsWith(this.keyPrefix));
32264
+ if (ourKeys.length > 0) {
32265
+ await this.asyncStorage.multiRemove(ourKeys);
32266
+ }
32267
+ }
32268
+ catch (error) {
32269
+ console.error('Failed to clear token storage:', error);
32270
+ }
32271
+ }
32272
+ }
32273
+
32047
32274
  // Conditionally require Keychain to avoid Web bundler errors
32048
32275
  let Keychain;
32049
32276
  if (reactNative.Platform.OS !== 'web') {
@@ -32070,6 +32297,7 @@ class ReactNativeSecureStorage {
32070
32297
  AUTH_STORAGE_KEYS.REFRESH_TOKEN,
32071
32298
  AUTH_STORAGE_KEYS.PROVIDER_TOKEN
32072
32299
  ]);
32300
+ this.fallbackStorage = new AsyncStorageTokenStorage(keyPrefix);
32073
32301
  }
32074
32302
  async set(key, value) {
32075
32303
  const prefixedKey = this.getKeyName(key);
@@ -32090,12 +32318,12 @@ class ReactNativeSecureStorage {
32090
32318
  catch (e) {
32091
32319
  console.warn(`[ReactNativeSecureStorage] Keychain set failed for ${key}, falling back to AsyncStorage`, e);
32092
32320
  // Fallback to AsyncStorage if Keychain fails
32093
- await AsyncStorage.setItem(prefixedKey, stringValue);
32321
+ await this.fallbackStorage.set(key, stringValue);
32094
32322
  }
32095
32323
  }
32096
32324
  else {
32097
32325
  // Store standard config/metadata in AsyncStorage
32098
- await AsyncStorage.setItem(prefixedKey, stringValue);
32326
+ await this.fallbackStorage.set(key, stringValue);
32099
32327
  }
32100
32328
  }
32101
32329
  async get(key) {
@@ -32115,7 +32343,7 @@ class ReactNativeSecureStorage {
32115
32343
  }
32116
32344
  // Fallback: Check AsyncStorage if not found in Keychain or Keychain failed
32117
32345
  try {
32118
- const val = await AsyncStorage.getItem(prefixedKey);
32346
+ const val = await this.fallbackStorage.get(key);
32119
32347
  return val ? this.tryParse(val) : null;
32120
32348
  }
32121
32349
  catch (e) {
@@ -32124,7 +32352,7 @@ class ReactNativeSecureStorage {
32124
32352
  }
32125
32353
  else {
32126
32354
  try {
32127
- const val = await AsyncStorage.getItem(prefixedKey);
32355
+ const val = await this.fallbackStorage.get(key);
32128
32356
  return val ? this.tryParse(val) : null;
32129
32357
  }
32130
32358
  catch (e) {
@@ -32145,10 +32373,10 @@ class ReactNativeSecureStorage {
32145
32373
  console.warn(`[ReactNativeSecureStorage] Failed to reset keychain for ${key}`, e);
32146
32374
  }
32147
32375
  // Always remove from fallback storage too, just in case
32148
- await AsyncStorage.removeItem(prefixedKey);
32376
+ await this.fallbackStorage.remove(key);
32149
32377
  }
32150
32378
  else {
32151
- await AsyncStorage.removeItem(prefixedKey);
32379
+ await this.fallbackStorage.remove(key);
32152
32380
  }
32153
32381
  }
32154
32382
  async clear() {
@@ -32165,11 +32393,7 @@ class ReactNativeSecureStorage {
32165
32393
  }
32166
32394
  // Clear AsyncStorage keys related to PERS
32167
32395
  try {
32168
- const allKeys = await AsyncStorage.getAllKeys();
32169
- const ourKeys = allKeys.filter(k => k.startsWith(this.keyPrefix));
32170
- if (ourKeys.length > 0) {
32171
- await AsyncStorage.multiRemove(ourKeys);
32172
- }
32396
+ await this.fallbackStorage.clear();
32173
32397
  }
32174
32398
  catch (e) {
32175
32399
  console.warn('[ReactNativeSecureStorage] Failed to clear AsyncStorage', e);
@@ -32238,119 +32462,6 @@ function createReactNativeAuthProvider(projectKey, config = {}) {
32238
32462
  });
32239
32463
  }
32240
32464
 
32241
- /**
32242
- * AsyncStorage Token Storage for React Native Mobile Platforms
32243
- *
32244
- * Bundler-agnostic AsyncStorage implementation for mobile platforms
32245
- */
32246
- /**
32247
- * Bundler-agnostic AsyncStorage wrapper
32248
- * Handles different module resolution patterns across bundlers (Metro, Webpack, Rollup, etc.)
32249
- */
32250
- class BundlerAgnosticAsyncStorage {
32251
- constructor(asyncStorageModule) {
32252
- // Try different import patterns to handle various bundlers
32253
- if (asyncStorageModule?.default?.getItem) {
32254
- // Metro/Webpack pattern: { default: { getItem, setItem, ... } }
32255
- this.storage = asyncStorageModule.default;
32256
- }
32257
- else if (asyncStorageModule?.getItem) {
32258
- // Direct export pattern: { getItem, setItem, ... }
32259
- this.storage = asyncStorageModule;
32260
- }
32261
- else if (typeof asyncStorageModule === 'function') {
32262
- // Function export pattern (some bundlers)
32263
- this.storage = asyncStorageModule();
32264
- }
32265
- else {
32266
- // Log the structure for debugging
32267
- console.error('[BundlerAgnosticAsyncStorage] Unknown AsyncStorage structure:', asyncStorageModule);
32268
- throw new Error('AsyncStorage methods not found. Expected structure with getItem/setItem methods. ' +
32269
- 'Make sure @react-native-async-storage/async-storage is properly installed.');
32270
- }
32271
- // Validate that we have the required methods
32272
- const requiredMethods = ['getItem', 'setItem', 'removeItem', 'getAllKeys', 'multiRemove'];
32273
- const missingMethods = requiredMethods.filter(method => typeof this.storage[method] !== 'function');
32274
- if (missingMethods.length > 0) {
32275
- throw new Error(`AsyncStorage missing required methods: ${missingMethods.join(', ')}. ` +
32276
- 'Ensure @react-native-async-storage/async-storage is properly installed and compatible.');
32277
- }
32278
- }
32279
- async getItem(key) {
32280
- return this.storage.getItem(key);
32281
- }
32282
- async setItem(key, value) {
32283
- return this.storage.setItem(key, value);
32284
- }
32285
- async removeItem(key) {
32286
- return this.storage.removeItem(key);
32287
- }
32288
- async getAllKeys() {
32289
- return this.storage.getAllKeys();
32290
- }
32291
- async multiRemove(keys) {
32292
- return this.storage.multiRemove(keys);
32293
- }
32294
- }
32295
- /**
32296
- * AsyncStorage implementation for mobile platforms
32297
- *
32298
- * This class is only used on mobile platforms (iOS/Android).
32299
- * Web platforms use LocalStorageTokenStorage from core SDK.
32300
- */
32301
- class AsyncStorageTokenStorage {
32302
- constructor(keyPrefix = 'pers_tokens_') {
32303
- this.keyPrefix = keyPrefix;
32304
- try {
32305
- // Initialize bundler-agnostic AsyncStorage wrapper
32306
- this.asyncStorage = new BundlerAgnosticAsyncStorage(AsyncStorage);
32307
- }
32308
- catch (error) {
32309
- console.error('[AsyncStorageTokenStorage] Failed to initialize:', error);
32310
- throw new Error('Failed to initialize AsyncStorage. Make sure @react-native-async-storage/async-storage is installed and ' +
32311
- 'this code is running on a React Native mobile platform (not web).');
32312
- }
32313
- }
32314
- async set(key, value) {
32315
- try {
32316
- await this.asyncStorage.setItem(`${this.keyPrefix}${key}`, value);
32317
- }
32318
- catch (error) {
32319
- console.error(`Failed to store token ${key}:`, error);
32320
- throw new Error(`Token storage failed: ${error}`);
32321
- }
32322
- }
32323
- async get(key) {
32324
- try {
32325
- return await this.asyncStorage.getItem(`${this.keyPrefix}${key}`);
32326
- }
32327
- catch (error) {
32328
- console.error(`Failed to retrieve token ${key}:`, error);
32329
- return null;
32330
- }
32331
- }
32332
- async remove(key) {
32333
- try {
32334
- await this.asyncStorage.removeItem(`${this.keyPrefix}${key}`);
32335
- }
32336
- catch (error) {
32337
- console.error(`Failed to remove token ${key}:`, error);
32338
- }
32339
- }
32340
- async clear() {
32341
- try {
32342
- const allKeys = await this.asyncStorage.getAllKeys();
32343
- const ourKeys = allKeys.filter(key => key.startsWith(this.keyPrefix));
32344
- if (ourKeys.length > 0) {
32345
- await this.asyncStorage.multiRemove(ourKeys);
32346
- }
32347
- }
32348
- catch (error) {
32349
- console.error('Failed to clear token storage:', error);
32350
- }
32351
- }
32352
- }
32353
-
32354
32465
  // Conditionally require quick-crypto for Native platforms only
32355
32466
  let crypto$1;
32356
32467
  if (reactNative.Platform.OS !== 'web') {
@@ -32363,7 +32474,6 @@ if (reactNative.Platform.OS !== 'web') {
32363
32474
  }
32364
32475
  else {
32365
32476
  // on Web, we shouldn't be using this provider anyway (Core SDK has WebDPoPProvider)
32366
- // But to be safe, we can mock or throw
32367
32477
  crypto$1 = {
32368
32478
  generateKeyPair: () => { throw new Error('ReactNativeDPoPProvider not supported on Web'); }
32369
32479
  };
@@ -32372,26 +32482,39 @@ class ReactNativeDPoPProvider {
32372
32482
  /**
32373
32483
  * Generates a new key pair (ES256 recommended)
32374
32484
  *
32375
- * Note: options.extractable is ignored because for React Native Keychain storage,
32376
- * we MUST export the keys as JWK/strings. We rely on the Keychain encryption
32377
- * for security at rest (High Security), making the key "Extractable" in memory
32378
- * but protected by hardware encryption when stored.
32485
+ * Uses WebCrypto API (crypto.subtle) for cross-platform compatibility.
32486
+ * Falls back to Node.js crypto API on iOS if needed.
32379
32487
  */
32380
32488
  async generateKeyPair(options) {
32381
- // Generate P-256 Key Pair
32489
+ // Try WebCrypto API first (works on both iOS and Android)
32490
+ if (crypto$1.subtle) {
32491
+ try {
32492
+ const keyPair = await crypto$1.subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, // extractable - required for JWK export
32493
+ ['sign', 'verify']);
32494
+ const publicKeyJwk = await crypto$1.subtle.exportKey('jwk', keyPair.publicKey);
32495
+ const privateKeyJwk = await crypto$1.subtle.exportKey('jwk', keyPair.privateKey);
32496
+ return {
32497
+ publicKey: publicKeyJwk,
32498
+ privateKey: privateKeyJwk
32499
+ };
32500
+ }
32501
+ catch (err) {
32502
+ console.warn('[DPoP] WebCrypto API failed, trying Node.js crypto API', err);
32503
+ }
32504
+ }
32505
+ // Fallback: Node.js crypto API (works on iOS)
32382
32506
  return new Promise((resolve, reject) => {
32383
32507
  crypto$1.generateKeyPair('ec', { namedCurve: 'P-256' }, (err, publicKey, privateKey) => {
32384
32508
  if (err)
32385
32509
  return reject(err);
32386
- // Export to JWK for SDK Compatibility
32387
- // We use 'export' because supportsObjects=false in our storage forces the SDK
32388
- // to expect serializable keys.
32389
- const pubJwk = publicKey.export({ format: 'jwk' });
32390
- const privJwk = privateKey.export({ format: 'jwk' });
32391
- resolve({
32392
- publicKey: pubJwk,
32393
- privateKey: privJwk
32394
- });
32510
+ try {
32511
+ const pJwk = publicKey.export({ format: 'jwk' });
32512
+ const prJwk = privateKey.export({ format: 'jwk' });
32513
+ resolve({ publicKey: pJwk, privateKey: prJwk });
32514
+ }
32515
+ catch (exportErr) {
32516
+ reject(exportErr);
32517
+ }
32395
32518
  });
32396
32519
  });
32397
32520
  }
@@ -32412,21 +32535,37 @@ class ReactNativeDPoPProvider {
32412
32535
  const b64Header = this.base64Url(JSON.stringify(header));
32413
32536
  const b64Payload = this.base64Url(JSON.stringify(finalPayload));
32414
32537
  const signingInput = `${b64Header}.${b64Payload}`;
32415
- // 4. Sign
32538
+ // 4. Sign - try WebCrypto first, fallback to Node.js crypto
32539
+ if (crypto$1.subtle) {
32540
+ try {
32541
+ const privateKey = await crypto$1.subtle.importKey('jwk', keyPair.privateKey, { name: 'ECDSA', namedCurve: 'P-256' }, false, ['sign']);
32542
+ const signatureBuffer = await crypto$1.subtle.sign({ name: 'ECDSA', hash: 'SHA-256' }, privateKey, buffer.Buffer.from(signingInput));
32543
+ // WebCrypto returns signature in IEEE P1363 format (r || s), which is what we need for JWT
32544
+ return `${signingInput}.${this.base64UrlBuffer(buffer.Buffer.from(signatureBuffer))}`;
32545
+ }
32546
+ catch (err) {
32547
+ console.warn('[DPoP] WebCrypto sign failed, trying Node.js crypto', err);
32548
+ }
32549
+ }
32550
+ // Fallback: Node.js crypto API
32416
32551
  const sign = crypto$1.createSign('SHA256');
32417
32552
  sign.update(signingInput);
32418
- // sign.end() is not required/available in quick-crypto as it doesn't strictly follow stream interface
32419
- // Import private key back from JWK to sign
32420
- // The keyPair.privateKey is a JsonWebKey object because we exported it earlier.
32421
- // quick-crypto createPrivateKey expects jwk object if format is jwk
32422
32553
  const privateKeyObj = crypto$1.createPrivateKey({ key: keyPair.privateKey, format: 'jwk' });
32423
32554
  const signature = sign.sign(privateKeyObj);
32424
- // signature is a Buffer in quick-crypto
32425
32555
  return `${signingInput}.${this.base64UrlBuffer(signature)}`;
32426
32556
  }
32427
32557
  async hashAccessToken(accessToken) {
32558
+ // Try WebCrypto first
32559
+ if (crypto$1.subtle) {
32560
+ try {
32561
+ const hashBuffer = await crypto$1.subtle.digest('SHA-256', buffer.Buffer.from(accessToken));
32562
+ return this.base64UrlBuffer(buffer.Buffer.from(hashBuffer));
32563
+ }
32564
+ catch (err) {
32565
+ // Fallback to Node.js crypto
32566
+ }
32567
+ }
32428
32568
  const hash = crypto$1.createHash('sha256').update(accessToken).digest();
32429
- // digest returns Buffer in quick-crypto
32430
32569
  return this.base64UrlBuffer(hash);
32431
32570
  }
32432
32571
  // --- Helpers ---
@@ -32434,7 +32573,6 @@ class ReactNativeDPoPProvider {
32434
32573
  return this.base64UrlBuffer(buffer.Buffer.from(str));
32435
32574
  }
32436
32575
  base64UrlBuffer(buf) {
32437
- // Ensure we have a Buffer
32438
32576
  const buffer$1 = buffer.Buffer.isBuffer(buf) ? buf : buffer.Buffer.from(buf);
32439
32577
  return buffer$1.toString('base64')
32440
32578
  .replace(/=/g, '')
@@ -32548,7 +32686,6 @@ const PersSDKProvider = ({ children, config }) => {
32548
32686
  const [isInitialized, setIsInitialized] = react.useState(false);
32549
32687
  const [isAuthenticated, setIsAuthenticated] = react.useState(false);
32550
32688
  const [user, setUser] = react.useState(null);
32551
- const [accountAddress, setAccountAddress] = react.useState(null);
32552
32689
  const initialize = react.useCallback(async (config) => {
32553
32690
  // Prevent multiple initializations
32554
32691
  if (isInitialized || initializingRef.current) {
@@ -32610,9 +32747,8 @@ const PersSDKProvider = ({ children, config }) => {
32610
32747
  });
32611
32748
  }
32612
32749
  }, [config, isInitialized, initialize]);
32613
- const setAuthenticationState = react.useCallback((user, accountAddress, isAuthenticated) => {
32750
+ const setAuthenticationState = react.useCallback((user, isAuthenticated) => {
32614
32751
  setUser(user);
32615
- setAccountAddress(accountAddress);
32616
32752
  setIsAuthenticated(isAuthenticated);
32617
32753
  }, []);
32618
32754
  const refreshUserData = react.useCallback(async () => {
@@ -32628,7 +32764,7 @@ const PersSDKProvider = ({ children, config }) => {
32628
32764
  throw error;
32629
32765
  }
32630
32766
  }, [sdk, isAuthenticated, isInitialized]);
32631
- const contextValue = {
32767
+ const contextValue = react.useMemo(() => ({
32632
32768
  // Main SDK instance
32633
32769
  sdk,
32634
32770
  // Manager shortcuts for convenience
@@ -32643,20 +32779,26 @@ const PersSDKProvider = ({ children, config }) => {
32643
32779
  tenants: sdk?.tenants || null,
32644
32780
  analytics: sdk?.analytics || null,
32645
32781
  donations: sdk?.donations || null,
32646
- // Legacy support (deprecated but kept for backward compatibility)
32647
- business: sdk?.businesses || null,
32648
32782
  // Platform-specific providers
32649
32783
  authProvider,
32650
32784
  // State
32651
32785
  isInitialized,
32652
32786
  isAuthenticated,
32653
32787
  user,
32654
- accountAddress,
32655
32788
  // Methods
32656
32789
  initialize,
32657
32790
  setAuthenticationState,
32658
32791
  refreshUserData,
32659
- };
32792
+ }), [
32793
+ sdk,
32794
+ authProvider,
32795
+ isInitialized,
32796
+ isAuthenticated,
32797
+ user,
32798
+ initialize,
32799
+ setAuthenticationState,
32800
+ refreshUserData
32801
+ ]);
32660
32802
  return (jsxRuntime.jsx(SDKContext.Provider, { value: contextValue, children: children }));
32661
32803
  };
32662
32804
  // Custom hook to use the SDK context
@@ -32706,7 +32848,7 @@ const usePersSDK = () => {
32706
32848
  * ```
32707
32849
  */
32708
32850
  const useAuth = () => {
32709
- const { sdk, authProvider, isInitialized, isAuthenticated, user, accountAddress, setAuthenticationState, refreshUserData } = usePersSDK();
32851
+ const { sdk, authProvider, isInitialized, isAuthenticated, user, setAuthenticationState, refreshUserData } = usePersSDK();
32710
32852
  /**
32711
32853
  * Authenticates a user with a JWT token
32712
32854
  *
@@ -32727,18 +32869,13 @@ const useAuth = () => {
32727
32869
  throw new Error('SDK not initialized. Call initialize() first.');
32728
32870
  }
32729
32871
  try {
32730
- console.log(`Logging in as ${userType}...`);
32731
32872
  // Set token in auth provider
32732
32873
  await authProvider.setAccessToken(jwtToken);
32733
32874
  // Perform login using the manager
32734
32875
  const result = await sdk.auth.loginWithToken(jwtToken, userType);
32735
32876
  const userData = result.user || result.admin;
32736
32877
  if (userData) {
32737
- const userAccountAddress = ('accountAddress' in userData && userData.accountAddress) ||
32738
- ('wallets' in userData && userData.wallets?.[0]?.address) ||
32739
- null;
32740
- setAuthenticationState(userData, userAccountAddress, true);
32741
- console.log('Login successful');
32878
+ setAuthenticationState(userData, true);
32742
32879
  return result;
32743
32880
  }
32744
32881
  else {
@@ -32767,7 +32904,6 @@ const useAuth = () => {
32767
32904
  throw new Error('SDK not initialized. Call initialize() first.');
32768
32905
  }
32769
32906
  try {
32770
- console.log('Logging in with raw user data...');
32771
32907
  // Use the raw data login from the auth manager
32772
32908
  const result = await sdk.auth.loginWithRawData(rawUserData);
32773
32909
  // Set token from result
@@ -32776,11 +32912,7 @@ const useAuth = () => {
32776
32912
  }
32777
32913
  const userData = result.user;
32778
32914
  if (userData) {
32779
- const userAccountAddress = userData.accountAddress ||
32780
- userData?.wallets?.[0]?.address ||
32781
- null;
32782
- setAuthenticationState(userData, userAccountAddress, true);
32783
- console.log('Raw data login successful');
32915
+ setAuthenticationState(userData, true);
32784
32916
  }
32785
32917
  else {
32786
32918
  throw new Error('No user data returned from raw data login');
@@ -32805,12 +32937,10 @@ const useAuth = () => {
32805
32937
  */
32806
32938
  const logout = react.useCallback(async () => {
32807
32939
  try {
32808
- console.log('Logging out...');
32809
32940
  if (authProvider) {
32810
32941
  await authProvider.clearTokens();
32811
32942
  }
32812
- setAuthenticationState(null, null, false);
32813
- console.log('Logout successful');
32943
+ setAuthenticationState(null, false);
32814
32944
  }
32815
32945
  catch (error) {
32816
32946
  console.error('Logout failed:', error);
@@ -32891,7 +33021,7 @@ const useAuth = () => {
32891
33021
  throw new Error('SDK not initialized. Call initialize() first.');
32892
33022
  }
32893
33023
  await sdk.auth.clearAuth();
32894
- setAuthenticationState(null, null, false);
33024
+ setAuthenticationState(null, false);
32895
33025
  }, [sdk, setAuthenticationState]);
32896
33026
  /**
32897
33027
  * Checks if the current authentication is valid (non-expired)
@@ -32916,7 +33046,6 @@ const useAuth = () => {
32916
33046
  isInitialized,
32917
33047
  isAuthenticated,
32918
33048
  user,
32919
- accountAddress,
32920
33049
  // Methods
32921
33050
  login,
32922
33051
  loginWithRawData,
@@ -32982,7 +33111,6 @@ const useTokens = () => {
32982
33111
  }
32983
33112
  try {
32984
33113
  const result = await sdk.tokens.getTokens();
32985
- console.log('Tokens fetched successfully:', result);
32986
33114
  return result;
32987
33115
  }
32988
33116
  catch (error) {
@@ -33009,7 +33137,6 @@ const useTokens = () => {
33009
33137
  }
33010
33138
  try {
33011
33139
  const result = await sdk.tokens.getActiveCreditToken();
33012
- console.log('Active credit token fetched successfully:', result);
33013
33140
  return result;
33014
33141
  }
33015
33142
  catch (error) {
@@ -33036,7 +33163,6 @@ const useTokens = () => {
33036
33163
  }
33037
33164
  try {
33038
33165
  const result = await sdk.tokens.getRewardTokens();
33039
- console.log('Reward tokens fetched successfully:', result);
33040
33166
  return result;
33041
33167
  }
33042
33168
  catch (error) {
@@ -33063,7 +33189,6 @@ const useTokens = () => {
33063
33189
  }
33064
33190
  try {
33065
33191
  const result = await sdk.tokens.getTokenTypes();
33066
- console.log('Token types fetched successfully:', result);
33067
33192
  return result;
33068
33193
  }
33069
33194
  catch (error) {
@@ -33090,7 +33215,6 @@ const useTokens = () => {
33090
33215
  }
33091
33216
  try {
33092
33217
  const result = await sdk.tokens.getStatusTokens();
33093
- console.log('Status tokens fetched successfully:', result);
33094
33218
  return result;
33095
33219
  }
33096
33220
  catch (error) {
@@ -33119,7 +33243,6 @@ const useTokens = () => {
33119
33243
  }
33120
33244
  try {
33121
33245
  const result = await sdk.tokens.getTokenByContract(contractAddress, contractTokenId);
33122
- console.log('Token by contract fetched successfully:', result);
33123
33246
  return result;
33124
33247
  }
33125
33248
  catch (error) {
@@ -33138,6 +33261,45 @@ const useTokens = () => {
33138
33261
  };
33139
33262
  };
33140
33263
 
33264
+ /**
33265
+ * Transaction statuses that allow signing
33266
+ */
33267
+ [exports.TransactionStatus.PENDING_SIGNATURE, exports.TransactionStatus.CREATED];
33268
+
33269
+ /**
33270
+ * Error codes for transaction signing operations
33271
+ */
33272
+ var TransactionSigningErrorCode;
33273
+ (function (TransactionSigningErrorCode) {
33274
+ TransactionSigningErrorCode["INVALID_TOKENS"] = "INVALID_TOKENS";
33275
+ TransactionSigningErrorCode["TRANSACTION_NOT_FOUND"] = "TRANSACTION_NOT_FOUND";
33276
+ TransactionSigningErrorCode["TRANSACTION_NOT_PENDING"] = "TRANSACTION_NOT_PENDING";
33277
+ TransactionSigningErrorCode["WALLET_NOT_AVAILABLE"] = "WALLET_NOT_AVAILABLE";
33278
+ TransactionSigningErrorCode["WEBAUTHN_OPERATION_IN_PROGRESS"] = "WEBAUTHN_OPERATION_IN_PROGRESS";
33279
+ TransactionSigningErrorCode["SIGNING_CANCELLED"] = "SIGNING_CANCELLED";
33280
+ TransactionSigningErrorCode["PERS_AUTH_FAILED"] = "PERS_AUTH_FAILED";
33281
+ TransactionSigningErrorCode["AUTH_FAILED"] = "AUTH_FAILED";
33282
+ TransactionSigningErrorCode["TRANSACTION_NOT_READY"] = "TRANSACTION_NOT_READY";
33283
+ TransactionSigningErrorCode["SUBMISSION_FAILED"] = "SUBMISSION_FAILED";
33284
+ TransactionSigningErrorCode["SERVER_ERROR"] = "SERVER_ERROR";
33285
+ TransactionSigningErrorCode["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
33286
+ })(TransactionSigningErrorCode || (TransactionSigningErrorCode = {}));
33287
+
33288
+ /**
33289
+ * Signing status types for type-safe status updates
33290
+ * Using const pattern instead of enum for better bundling compatibility
33291
+ */
33292
+ const SigningStatus = {
33293
+ INITIALIZING: 'initializing',
33294
+ AUTHENTICATING: 'authenticating',
33295
+ PREPARING: 'preparing',
33296
+ SIGNING: 'signing',
33297
+ SUBMITTING: 'submitting',
33298
+ COMPLETED: 'completed',
33299
+ ERROR: 'error',
33300
+ EXPIRED: 'expired'
33301
+ };
33302
+
33141
33303
  // Dynamic import the signer SDK to avoid build issues with static dependencies
33142
33304
  let createPersSignerSDK = null;
33143
33305
  try {
@@ -33330,6 +33492,8 @@ const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0
33330
33492
  const useTransactionSigner = () => {
33331
33493
  // const { isInitialized, isAuthenticated, user } = usePersSDK();
33332
33494
  const [isSignerInitialized, setIsSignerInitialized] = react.useState(false);
33495
+ const [currentStatus, setCurrentStatus] = react.useState(null);
33496
+ const [statusMessage, setStatusMessage] = react.useState(null);
33333
33497
  const signerSDKRef = react.useRef(null);
33334
33498
  // Auto-initialize signer SDK when PERS SDK is ready
33335
33499
  react.useEffect(() => {
@@ -33378,6 +33542,7 @@ const useTransactionSigner = () => {
33378
33542
  *
33379
33543
  * @param {string} jwt - JWT token containing transaction ID and user information
33380
33544
  * Must include: `transactionId`, `identifierEmail`, `tenantId`
33545
+ * @param {StatusCallback} [onStatusUpdate] - Optional callback for real-time status updates
33381
33546
  * @returns {Promise<SubmissionResult>} Complete transaction result
33382
33547
  *
33383
33548
  * @throws {Error} 'Transaction signer not initialized' - Hook not ready
@@ -33400,6 +33565,15 @@ const useTransactionSigner = () => {
33400
33565
  * ```
33401
33566
  *
33402
33567
  * @example
33568
+ * **With Status Updates:**
33569
+ * ```typescript
33570
+ * const result = await signAndSubmitTransactionWithJWT(jwtToken, (status, message) => {
33571
+ * console.log(`Status: ${status} - ${message}`);
33572
+ * setStatusText(message);
33573
+ * });
33574
+ * ```
33575
+ *
33576
+ * @example
33403
33577
  * **With Error Handling:**
33404
33578
  * ```typescript
33405
33579
  * try {
@@ -33434,20 +33608,30 @@ const useTransactionSigner = () => {
33434
33608
  *
33435
33609
  * @see {@link SubmissionResult} for detailed result structure
33436
33610
  */
33437
- const signAndSubmitTransactionWithJWT = react.useCallback(async (jwt) => {
33611
+ const signAndSubmitTransactionWithJWT = react.useCallback(async (jwt, onStatusUpdate) => {
33438
33612
  if (!isSignerInitialized || !signerSDKRef.current) {
33439
33613
  throw new Error('Transaction signer not initialized');
33440
33614
  }
33441
33615
  if (!createPersSignerSDK) {
33442
33616
  throw new Error('PERS Signer SDK not available. Blockchain signing is not supported.');
33443
33617
  }
33618
+ // Create status callback wrapper that updates both hook state and calls user callback
33619
+ const statusCallback = {
33620
+ onStatusUpdate: (status, message, data) => {
33621
+ setCurrentStatus(status);
33622
+ setStatusMessage(message);
33623
+ onStatusUpdate?.(status, message, data);
33624
+ }
33625
+ };
33444
33626
  try {
33445
33627
  // Use the actual SDK method that handles the complete sign + submit flow
33446
- const submissionResult = await signerSDKRef.current.signAndSubmitPersTransaction(jwt);
33628
+ const submissionResult = await signerSDKRef.current.signAndSubmitPersTransaction(jwt, statusCallback);
33447
33629
  return submissionResult;
33448
33630
  }
33449
33631
  catch (error) {
33450
33632
  console.error('[useTransactionSigner] JWT transaction signing failed:', error);
33633
+ setCurrentStatus(SigningStatus.ERROR);
33634
+ setStatusMessage(error instanceof Error ? error.message : 'Transaction failed');
33451
33635
  throw error; // Re-throw to maintain error handling upstream
33452
33636
  }
33453
33637
  }, [isSignerInitialized]);
@@ -33459,6 +33643,7 @@ const useTransactionSigner = () => {
33459
33643
  * from authentication to blockchain submission in a single call.
33460
33644
  *
33461
33645
  * @param {string} jwt - JWT token with transaction and user data
33646
+ * @param {StatusCallback} [onStatusUpdate] - Optional callback for real-time status updates
33462
33647
  * @returns {Promise<SubmissionResult>} Transaction result with hash and status
33463
33648
  */
33464
33649
  signAndSubmitTransactionWithJWT,
@@ -33504,6 +33689,36 @@ const useTransactionSigner = () => {
33504
33689
  * ```
33505
33690
  */
33506
33691
  isSignerAvailable: isSignerInitialized && !!createPersSignerSDK,
33692
+ /**
33693
+ * Current signing status for UI feedback
33694
+ *
33695
+ * Tracks the current state of the signing process. Use this to show
33696
+ * progress indicators or status messages during transaction signing.
33697
+ *
33698
+ * Possible values: 'initializing', 'authenticating', 'preparing',
33699
+ * 'signing', 'submitting', 'completed', 'error', 'expired'
33700
+ *
33701
+ * @example
33702
+ * ```typescript
33703
+ * const { currentStatus, statusMessage } = useTransactionSigner();
33704
+ *
33705
+ * return (
33706
+ * <View>
33707
+ * {currentStatus && (
33708
+ * <Text>Status: {statusMessage}</Text>
33709
+ * )}
33710
+ * </View>
33711
+ * );
33712
+ * ```
33713
+ */
33714
+ currentStatus,
33715
+ /**
33716
+ * Human-readable status message
33717
+ *
33718
+ * Provides a user-friendly description of the current signing status.
33719
+ * Updates in real-time as the transaction progresses.
33720
+ */
33721
+ statusMessage,
33507
33722
  };
33508
33723
  };
33509
33724
 
@@ -33545,7 +33760,7 @@ const useTransactionSigner = () => {
33545
33760
  */
33546
33761
  const useTransactions = () => {
33547
33762
  const { sdk, isInitialized, isAuthenticated } = usePersSDK();
33548
- const { signAndSubmitTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
33763
+ const { signAndSubmitTransactionWithJWT, isSignerAvailable, currentStatus, statusMessage } = useTransactionSigner();
33549
33764
  if (!isAuthenticated && isInitialized) {
33550
33765
  console.warn('SDK not authenticated. Some transaction operations may fail.');
33551
33766
  }
@@ -33567,29 +33782,29 @@ const useTransactions = () => {
33567
33782
  * recipient: '0x123...',
33568
33783
  * tokenId: 'token-123'
33569
33784
  * };
33570
- * const result = await createTransaction(request);
33785
+ * const result = await createTransaction(request, (status, message) => {
33786
+ * console.log(`Status: ${status} - ${message}`);
33787
+ * });
33571
33788
  * console.log('Transaction created:', result);
33572
33789
  * ```
33573
33790
  */
33574
- const createTransaction = react.useCallback(async (request) => {
33791
+ const createTransaction = react.useCallback(async (request, onStatusUpdate) => {
33575
33792
  if (!isInitialized || !sdk) {
33576
33793
  throw new Error('SDK not initialized. Call initialize() first.');
33577
33794
  }
33578
33795
  try {
33579
33796
  const result = await sdk.transactions.createTransaction(request);
33580
- console.log('Transaction created successfully:', result);
33581
33797
  // Check if transaction requires signing (contains actionable authToken)
33582
33798
  // Type assertion needed as TransactionRequestResponseDTO type may not include all dynamic properties
33583
33799
  const txToken = result?.actionable?.authToken;
33584
33800
  if (txToken) {
33585
- console.log('[useTransactions] Transaction requires signing, attempting automatic signature...');
33586
33801
  try {
33587
33802
  if (!isSignerAvailable) {
33588
33803
  console.warn('[useTransactions] Transaction signer not available, skipping automatic signing');
33589
33804
  return result;
33590
33805
  }
33591
33806
  // Automatically sign the transaction using the authToken
33592
- const signingResult = await signAndSubmitTransactionWithJWT(txToken);
33807
+ const signingResult = await signAndSubmitTransactionWithJWT(txToken, onStatusUpdate);
33593
33808
  if (signingResult.success) {
33594
33809
  console.log('[useTransactions] Transaction signed successfully:', signingResult.transactionHash);
33595
33810
  // Return the original result - the transaction is now signed and will be processed
@@ -33634,7 +33849,6 @@ const useTransactions = () => {
33634
33849
  }
33635
33850
  try {
33636
33851
  const result = await sdk.transactions.getTransactionById(transactionId);
33637
- console.log('Transaction fetched successfully:', result);
33638
33852
  return result;
33639
33853
  }
33640
33854
  catch (error) {
@@ -33662,7 +33876,6 @@ const useTransactions = () => {
33662
33876
  }
33663
33877
  try {
33664
33878
  const result = await sdk.transactions.getUserTransactionHistory(role);
33665
- console.log('Transaction history fetched successfully:', result);
33666
33879
  return result;
33667
33880
  }
33668
33881
  catch (error) {
@@ -33689,7 +33902,6 @@ const useTransactions = () => {
33689
33902
  }
33690
33903
  try {
33691
33904
  const result = await sdk.transactions.getPaginatedTransactions(params);
33692
- console.log('Paginated transactions fetched successfully:', result);
33693
33905
  return result;
33694
33906
  }
33695
33907
  catch (error) {
@@ -33703,7 +33915,6 @@ const useTransactions = () => {
33703
33915
  }
33704
33916
  try {
33705
33917
  const result = await sdk.transactions.exportTransactionsCSV();
33706
- console.log('Transactions CSV exported successfully');
33707
33918
  return result;
33708
33919
  }
33709
33920
  catch (error) {
@@ -33719,6 +33930,9 @@ const useTransactions = () => {
33719
33930
  getPaginatedTransactions,
33720
33931
  exportTransactionsCSV,
33721
33932
  isAvailable: isInitialized && !!sdk?.transactions,
33933
+ // Expose signing status for UI feedback
33934
+ signingStatus: currentStatus,
33935
+ signingStatusMessage: statusMessage,
33722
33936
  };
33723
33937
  };
33724
33938
 
@@ -33777,7 +33991,6 @@ const useBusiness = () => {
33777
33991
  }
33778
33992
  try {
33779
33993
  const result = await sdk.businesses.getActiveBusinesses();
33780
- console.log('Active businesses fetched successfully:', result);
33781
33994
  return result;
33782
33995
  }
33783
33996
  catch (error) {
@@ -33804,7 +34017,6 @@ const useBusiness = () => {
33804
34017
  }
33805
34018
  try {
33806
34019
  const result = await sdk.businesses.getBusinessTypes();
33807
- console.log('Business types fetched successfully:', result);
33808
34020
  return result;
33809
34021
  }
33810
34022
  catch (error) {
@@ -33818,7 +34030,6 @@ const useBusiness = () => {
33818
34030
  }
33819
34031
  try {
33820
34032
  const result = await sdk.businesses.getBusinessById(businessId);
33821
- console.log('Business fetched successfully:', result);
33822
34033
  return result;
33823
34034
  }
33824
34035
  catch (error) {
@@ -33832,7 +34043,6 @@ const useBusiness = () => {
33832
34043
  }
33833
34044
  try {
33834
34045
  const result = await sdk.businesses.getBusinesses();
33835
- console.log('All businesses fetched successfully:', result);
33836
34046
  return result;
33837
34047
  }
33838
34048
  catch (error) {
@@ -33846,7 +34056,6 @@ const useBusiness = () => {
33846
34056
  }
33847
34057
  try {
33848
34058
  const result = await sdk.businesses.getBusinessByAccount(accountAddress);
33849
- console.log('Business by account fetched successfully:', result);
33850
34059
  return result;
33851
34060
  }
33852
34061
  catch (error) {
@@ -33860,7 +34069,6 @@ const useBusiness = () => {
33860
34069
  }
33861
34070
  try {
33862
34071
  const result = await sdk.businesses.getBusinessesByType(typeId);
33863
- console.log('Businesses by type fetched successfully:', result);
33864
34072
  return result;
33865
34073
  }
33866
34074
  catch (error) {
@@ -33889,7 +34097,6 @@ const useBusiness = () => {
33889
34097
  }
33890
34098
  try {
33891
34099
  const result = await sdk.businesses.createBusiness(displayName);
33892
- console.log('Business created successfully:', result);
33893
34100
  return result;
33894
34101
  }
33895
34102
  catch (error) {
@@ -33903,7 +34110,6 @@ const useBusiness = () => {
33903
34110
  }
33904
34111
  try {
33905
34112
  const result = await sdk.businesses.updateBusiness(businessId, businessData);
33906
- console.log('Business updated successfully:', result);
33907
34113
  return result;
33908
34114
  }
33909
34115
  catch (error) {
@@ -33917,7 +34123,6 @@ const useBusiness = () => {
33917
34123
  }
33918
34124
  try {
33919
34125
  const result = await sdk.businesses.toggleBusinessStatus(businessId, toggleData);
33920
- console.log('Business status toggled successfully:', result);
33921
34126
  return result;
33922
34127
  }
33923
34128
  catch (error) {
@@ -33947,7 +34152,6 @@ const useCampaigns = () => {
33947
34152
  }
33948
34153
  try {
33949
34154
  const result = await sdk.campaigns.getActiveCampaigns();
33950
- console.log('Active campaigns fetched successfully:', result);
33951
34155
  return result;
33952
34156
  }
33953
34157
  catch (error) {
@@ -33961,7 +34165,6 @@ const useCampaigns = () => {
33961
34165
  }
33962
34166
  try {
33963
34167
  const result = await sdk.campaigns.getCampaignById(campaignId);
33964
- console.log('Campaign fetched successfully:', result);
33965
34168
  return result;
33966
34169
  }
33967
34170
  catch (error) {
@@ -33977,9 +34180,7 @@ const useCampaigns = () => {
33977
34180
  throw new Error('SDK not authenticated. claimCampaign requires authentication.');
33978
34181
  }
33979
34182
  try {
33980
- console.log('Claiming campaign with request:', request);
33981
34183
  const result = await sdk.campaigns.claimCampaign(request);
33982
- console.log('Campaign claimed successfully:', result);
33983
34184
  return result;
33984
34185
  }
33985
34186
  catch (error) {
@@ -33997,7 +34198,6 @@ const useCampaigns = () => {
33997
34198
  }
33998
34199
  try {
33999
34200
  const result = await sdk.campaigns.getUserClaims();
34000
- console.log('User claims fetched successfully:', result);
34001
34201
  return result;
34002
34202
  }
34003
34203
  catch (error) {
@@ -34011,7 +34211,6 @@ const useCampaigns = () => {
34011
34211
  }
34012
34212
  try {
34013
34213
  const result = await sdk.campaigns.getCampaignTriggers();
34014
- console.log('Campaign triggers fetched successfully:', result);
34015
34214
  return result;
34016
34215
  }
34017
34216
  catch (error) {
@@ -34026,7 +34225,6 @@ const useCampaigns = () => {
34026
34225
  }
34027
34226
  try {
34028
34227
  const result = await sdk.campaigns.getAllCampaigns(active);
34029
- console.log('All campaigns fetched successfully:', result);
34030
34228
  return result;
34031
34229
  }
34032
34230
  catch (error) {
@@ -34040,7 +34238,6 @@ const useCampaigns = () => {
34040
34238
  }
34041
34239
  try {
34042
34240
  const result = await sdk.campaigns.getCampaignClaims();
34043
- console.log('Campaign claims fetched successfully:', result);
34044
34241
  return result;
34045
34242
  }
34046
34243
  catch (error) {
@@ -34054,7 +34251,6 @@ const useCampaigns = () => {
34054
34251
  }
34055
34252
  try {
34056
34253
  const result = await sdk.campaigns.getCampaignClaimsByUserId(userId);
34057
- console.log('Campaign claims by user ID fetched successfully:', result);
34058
34254
  return result;
34059
34255
  }
34060
34256
  catch (error) {
@@ -34068,7 +34264,6 @@ const useCampaigns = () => {
34068
34264
  }
34069
34265
  try {
34070
34266
  const result = await sdk.campaigns.getCampaignClaimsByBusinessId(businessId);
34071
- console.log('Campaign claims by business ID fetched successfully:', result);
34072
34267
  return result;
34073
34268
  }
34074
34269
  catch (error) {
@@ -34092,14 +34287,13 @@ const useCampaigns = () => {
34092
34287
 
34093
34288
  const useRedemptions = () => {
34094
34289
  const { sdk, isInitialized, isAuthenticated } = usePersSDK();
34095
- const { signAndSubmitTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
34290
+ const { signAndSubmitTransactionWithJWT, isSignerAvailable, currentStatus, statusMessage } = useTransactionSigner();
34096
34291
  const getActiveRedemptions = react.useCallback(async () => {
34097
34292
  if (!isInitialized || !sdk) {
34098
34293
  throw new Error('SDK not initialized. Call initialize() first.');
34099
34294
  }
34100
34295
  try {
34101
34296
  const result = await sdk.redemptions.getActiveRedemptions();
34102
- console.log('Active redemptions fetched successfully:', result);
34103
34297
  return result;
34104
34298
  }
34105
34299
  catch (error) {
@@ -34117,7 +34311,6 @@ const useRedemptions = () => {
34117
34311
  }
34118
34312
  try {
34119
34313
  const result = await sdk.redemptions.getUserRedemptions();
34120
- console.log('User redemptions fetched successfully:', result);
34121
34314
  return result;
34122
34315
  }
34123
34316
  catch (error) {
@@ -34125,7 +34318,7 @@ const useRedemptions = () => {
34125
34318
  throw error;
34126
34319
  }
34127
34320
  }, [sdk, isInitialized, isAuthenticated]);
34128
- const redeem = react.useCallback(async (redemptionId) => {
34321
+ const redeem = react.useCallback(async (redemptionId, onStatusUpdate) => {
34129
34322
  if (!isInitialized || !sdk) {
34130
34323
  throw new Error('SDK not initialized. Call initialize() first.');
34131
34324
  }
@@ -34133,18 +34326,12 @@ const useRedemptions = () => {
34133
34326
  throw new Error('SDK not authenticated. redeem requires authentication.');
34134
34327
  }
34135
34328
  try {
34136
- console.log('Redeeming redemption:', redemptionId);
34137
34329
  const result = await sdk.redemptions.redeem(redemptionId);
34138
- // Check if result has signing fields and sign transaction if required and signer is available
34139
- console.log('Redemption processed successfully:', result);
34140
34330
  const txToken = result.senderTransaction?.actionable?.authToken;
34141
34331
  if (txToken && isSignerAvailable) {
34142
- console.log('Transaction requires blockchain signing, processing with WebAuthn signer...');
34143
34332
  try {
34144
- const signingResult = await signAndSubmitTransactionWithJWT(txToken);
34145
- console.log('Blockchain signing result:', signingResult);
34333
+ const signingResult = await signAndSubmitTransactionWithJWT(txToken, onStatusUpdate);
34146
34334
  if (signingResult.success) {
34147
- console.log('Transaction signed successfully:', signingResult.transactionHash);
34148
34335
  // Return enhanced result with signing information
34149
34336
  return {
34150
34337
  ...result,
@@ -34182,9 +34369,7 @@ const useRedemptions = () => {
34182
34369
  throw new Error('SDK not initialized. Call initialize() first.');
34183
34370
  }
34184
34371
  try {
34185
- console.log('Creating redemption offer with data:', redemptionData);
34186
34372
  const result = await sdk.redemptions.createRedemption(redemptionData);
34187
- console.log('Redemption offer created successfully:', result);
34188
34373
  return result;
34189
34374
  }
34190
34375
  catch (error) {
@@ -34198,7 +34383,6 @@ const useRedemptions = () => {
34198
34383
  }
34199
34384
  try {
34200
34385
  const result = await sdk.redemptions.getAllRedemptions(active);
34201
- console.log('All redemptions fetched successfully:', result);
34202
34386
  return result;
34203
34387
  }
34204
34388
  catch (error) {
@@ -34212,7 +34396,6 @@ const useRedemptions = () => {
34212
34396
  }
34213
34397
  try {
34214
34398
  const result = await sdk.redemptions.getRedemptionTypes();
34215
- console.log('Redemption types fetched successfully:', result);
34216
34399
  return result;
34217
34400
  }
34218
34401
  catch (error) {
@@ -34226,7 +34409,6 @@ const useRedemptions = () => {
34226
34409
  }
34227
34410
  try {
34228
34411
  const result = await sdk.redemptions.updateRedemption(redemptionId, redemptionData);
34229
- console.log('Redemption updated successfully:', result);
34230
34412
  return result;
34231
34413
  }
34232
34414
  catch (error) {
@@ -34240,7 +34422,6 @@ const useRedemptions = () => {
34240
34422
  }
34241
34423
  try {
34242
34424
  const result = await sdk.redemptions.toggleRedemptionStatus(redemptionId);
34243
- console.log('Redemption status toggled successfully:', result);
34244
34425
  return result;
34245
34426
  }
34246
34427
  catch (error) {
@@ -34258,6 +34439,9 @@ const useRedemptions = () => {
34258
34439
  updateRedemption,
34259
34440
  toggleRedemptionStatus,
34260
34441
  isAvailable: isInitialized && !!sdk?.redemptions,
34442
+ // Expose signing status for UI feedback
34443
+ signingStatus: currentStatus,
34444
+ signingStatusMessage: statusMessage,
34261
34445
  };
34262
34446
  };
34263
34447
 
@@ -34266,56 +34450,53 @@ const useRedemptions = () => {
34266
34450
  *
34267
34451
  * Provides comprehensive Web3 functionality including token balance queries,
34268
34452
  * metadata retrieval, collection management, IPFS resolution, and blockchain
34269
- * explorer integration. Supports multi-chain operations and wallet management.
34453
+ * explorer integration. Supports multi-chain operations.
34454
+ *
34455
+ * Note: Wallet addresses should be obtained from `user.wallets` via `usePersSDK()`.
34270
34456
  *
34271
34457
  * @returns Web3 hook with methods for blockchain operations
34272
34458
  *
34273
34459
  * @example
34274
34460
  * ```typescript
34275
34461
  * function Web3Component() {
34276
- * const {
34277
- * getTokenBalance,
34278
- * getTokenMetadata,
34279
- * getWalletInfo,
34280
- * accountAddress
34281
- * } = useWeb3();
34462
+ * const { user } = usePersSDK();
34463
+ * const { getTokenBalance, getTokenMetadata } = useWeb3();
34464
+ *
34465
+ * // Get wallet address from user
34466
+ * const walletAddress = user?.wallets?.[0]?.address;
34282
34467
  *
34283
34468
  * const loadTokenData = async () => {
34284
- * try {
34285
- * if (!accountAddress) {
34286
- * console.log('No wallet connected');
34287
- * return;
34288
- * }
34469
+ * if (!walletAddress) {
34470
+ * console.log('No wallet connected');
34471
+ * return;
34472
+ * }
34289
34473
  *
34290
- * const balance = await getTokenBalance({
34291
- * walletAddress: accountAddress,
34292
- * contractAddress: '0x123...',
34293
- * chainId: 1
34294
- * });
34474
+ * const balance = await getTokenBalance({
34475
+ * walletAddress,
34476
+ * contractAddress: '0x123...',
34477
+ * chainId: 1
34478
+ * });
34295
34479
  *
34296
- * console.log('Token balance:', balance);
34297
- * } catch (error) {
34298
- * console.error('Failed to load token data:', error);
34299
- * }
34480
+ * console.log('Token balance:', balance);
34300
34481
  * };
34301
34482
  *
34302
34483
  * return (
34303
- * <div>
34304
- * {accountAddress ? (
34305
- * <div>
34306
- * <p>Wallet: {accountAddress}</p>
34307
- * <button onClick={loadTokenData}>Load Tokens</button>
34308
- * </div>
34484
+ * <View>
34485
+ * {walletAddress ? (
34486
+ * <View>
34487
+ * <Text>Wallet: {walletAddress}</Text>
34488
+ * <Button onPress={loadTokenData} title="Load Tokens" />
34489
+ * </View>
34309
34490
  * ) : (
34310
- * <p>No wallet connected</p>
34491
+ * <Text>No wallet connected</Text>
34311
34492
  * )}
34312
- * </div>
34493
+ * </View>
34313
34494
  * );
34314
34495
  * }
34315
34496
  * ```
34316
34497
  */
34317
34498
  const useWeb3 = () => {
34318
- const { sdk, isInitialized, isAuthenticated, accountAddress } = usePersSDK();
34499
+ const { sdk, isInitialized, isAuthenticated } = usePersSDK();
34319
34500
  if (!isAuthenticated && isInitialized) {
34320
34501
  console.warn('SDK not authenticated. Some web3 operations may fail.');
34321
34502
  }
@@ -34339,13 +34520,11 @@ const useWeb3 = () => {
34339
34520
  * ```
34340
34521
  */
34341
34522
  const getTokenBalance = react.useCallback(async (request) => {
34342
- console.log('[useWeb3] getTokenBalance called with request:', request);
34343
34523
  if (!isInitialized || !sdk) {
34344
34524
  throw new Error('SDK not initialized. Call initialize() first.');
34345
34525
  }
34346
34526
  try {
34347
34527
  const result = await sdk.web3.getTokenBalance(request);
34348
- console.log('Token balance fetched successfully:', result);
34349
34528
  return result;
34350
34529
  }
34351
34530
  catch (error) {
@@ -34369,7 +34548,7 @@ const useWeb3 = () => {
34369
34548
  * chainId: 1
34370
34549
  * });
34371
34550
  * console.log('NFT name:', metadata?.name);
34372
- * console.log('NFT image:', metadata?.image);
34551
+ * console.log('NFT image:', metadata?.imageUrl); // IPFS URLs auto-resolved to HTTPS
34373
34552
  * ```
34374
34553
  */
34375
34554
  const getTokenMetadata = react.useCallback(async (request) => {
@@ -34378,7 +34557,6 @@ const useWeb3 = () => {
34378
34557
  }
34379
34558
  try {
34380
34559
  const result = await sdk.web3.getTokenMetadata(request);
34381
- console.log('Token metadata fetched successfully:', result);
34382
34560
  return result;
34383
34561
  }
34384
34562
  catch (error) {
@@ -34392,7 +34570,6 @@ const useWeb3 = () => {
34392
34570
  }
34393
34571
  try {
34394
34572
  const result = await sdk.web3.getTokenCollection(request);
34395
- console.log('Token collection fetched successfully:', result);
34396
34573
  return result;
34397
34574
  }
34398
34575
  catch (error) {
@@ -34406,7 +34583,6 @@ const useWeb3 = () => {
34406
34583
  }
34407
34584
  try {
34408
34585
  const result = await sdk.web3.resolveIPFSUrl(url, chainId);
34409
- console.log('IPFS URL resolved successfully:', result);
34410
34586
  return result;
34411
34587
  }
34412
34588
  catch (error) {
@@ -34420,7 +34596,6 @@ const useWeb3 = () => {
34420
34596
  }
34421
34597
  try {
34422
34598
  const result = await sdk.web3.fetchAndProcessMetadata(tokenUri, chainId);
34423
- console.log('Metadata fetched and processed successfully:', result);
34424
34599
  return result;
34425
34600
  }
34426
34601
  catch (error) {
@@ -34434,7 +34609,6 @@ const useWeb3 = () => {
34434
34609
  }
34435
34610
  try {
34436
34611
  const result = await sdk.web3.getChainDataById(chainId);
34437
- console.log('Chain data fetched successfully:', result);
34438
34612
  return result;
34439
34613
  }
34440
34614
  catch (error) {
@@ -34448,7 +34622,6 @@ const useWeb3 = () => {
34448
34622
  }
34449
34623
  try {
34450
34624
  const result = await sdk.web3.getExplorerUrl(chainId, address, type);
34451
- console.log('Explorer URL generated successfully:', result);
34452
34625
  return result;
34453
34626
  }
34454
34627
  catch (error) {
@@ -34456,19 +34629,6 @@ const useWeb3 = () => {
34456
34629
  throw error;
34457
34630
  }
34458
34631
  }, [sdk, isInitialized]);
34459
- const getWalletInfo = react.useCallback(async () => {
34460
- if (!isInitialized) {
34461
- throw new Error('SDK not initialized. Call initialize() first.');
34462
- }
34463
- if (!accountAddress) {
34464
- console.warn('No account address available');
34465
- return null;
34466
- }
34467
- return {
34468
- address: accountAddress,
34469
- isConnected: !!accountAddress,
34470
- };
34471
- }, [isInitialized, accountAddress]);
34472
34632
  return {
34473
34633
  getTokenBalance,
34474
34634
  getTokenMetadata,
@@ -34477,8 +34637,6 @@ const useWeb3 = () => {
34477
34637
  fetchAndProcessMetadata,
34478
34638
  getChainDataById,
34479
34639
  getExplorerUrl,
34480
- getWalletInfo,
34481
- accountAddress: isInitialized ? accountAddress : null,
34482
34640
  isAvailable: isInitialized && !!sdk?.web3,
34483
34641
  };
34484
34642
  };
@@ -34491,7 +34649,6 @@ const usePurchases = () => {
34491
34649
  }
34492
34650
  try {
34493
34651
  const result = await sdk.purchases.createPaymentIntent(amount, currency, receiptEmail, description);
34494
- console.log('Payment intent created successfully:', result);
34495
34652
  return result;
34496
34653
  }
34497
34654
  catch (error) {
@@ -34505,7 +34662,6 @@ const usePurchases = () => {
34505
34662
  }
34506
34663
  try {
34507
34664
  const result = await sdk.purchases.getActivePurchaseTokens();
34508
- console.log('Active purchase tokens fetched successfully:', result);
34509
34665
  return result;
34510
34666
  }
34511
34667
  catch (error) {
@@ -34522,7 +34678,6 @@ const usePurchases = () => {
34522
34678
  }
34523
34679
  try {
34524
34680
  const result = await sdk.purchases.getAllUserPurchases();
34525
- console.log('User purchases fetched successfully:', result);
34526
34681
  return result;
34527
34682
  }
34528
34683
  catch (error) {
@@ -34559,7 +34714,6 @@ const useTenants = () => {
34559
34714
  }
34560
34715
  try {
34561
34716
  const result = await sdk.tenants.getClientConfig();
34562
- console.log('Client config fetched successfully:', result);
34563
34717
  return result;
34564
34718
  }
34565
34719
  catch (error) {
@@ -34573,7 +34727,6 @@ const useTenants = () => {
34573
34727
  }
34574
34728
  try {
34575
34729
  const result = await sdk.tenants.getLoginToken();
34576
- console.log('Login token fetched successfully');
34577
34730
  return result;
34578
34731
  }
34579
34732
  catch (error) {
@@ -34587,7 +34740,6 @@ const useTenants = () => {
34587
34740
  }
34588
34741
  try {
34589
34742
  const result = await sdk.tenants.getAdmins();
34590
- console.log('Admins fetched successfully:', result);
34591
34743
  return result;
34592
34744
  }
34593
34745
  catch (error) {
@@ -34615,7 +34767,6 @@ const useUsers = () => {
34615
34767
  }
34616
34768
  try {
34617
34769
  const result = await sdk.users.getCurrentUser();
34618
- console.log('Current user fetched successfully:', result);
34619
34770
  return result;
34620
34771
  }
34621
34772
  catch (error) {
@@ -34632,7 +34783,6 @@ const useUsers = () => {
34632
34783
  }
34633
34784
  try {
34634
34785
  const result = await sdk.users.updateCurrentUser(userData);
34635
- console.log('Current user updated successfully:', result);
34636
34786
  return result;
34637
34787
  }
34638
34788
  catch (error) {
@@ -34646,7 +34796,6 @@ const useUsers = () => {
34646
34796
  }
34647
34797
  try {
34648
34798
  const result = await sdk.users.getUserById(userId);
34649
- console.log('User fetched successfully:', result);
34650
34799
  return result;
34651
34800
  }
34652
34801
  catch (error) {
@@ -34660,7 +34809,6 @@ const useUsers = () => {
34660
34809
  }
34661
34810
  try {
34662
34811
  const result = await sdk.users.getAllUsersPublic(filter);
34663
- console.log('Public users fetched successfully:', result);
34664
34812
  return result;
34665
34813
  }
34666
34814
  catch (error) {
@@ -34675,7 +34823,6 @@ const useUsers = () => {
34675
34823
  }
34676
34824
  try {
34677
34825
  const result = await sdk.users.getAllUsers();
34678
- console.log('All users fetched successfully:', result);
34679
34826
  return result;
34680
34827
  }
34681
34828
  catch (error) {
@@ -34689,7 +34836,6 @@ const useUsers = () => {
34689
34836
  }
34690
34837
  try {
34691
34838
  const result = await sdk.users.updateUser(userId, userData);
34692
- console.log('User updated successfully:', result);
34693
34839
  return result;
34694
34840
  }
34695
34841
  catch (error) {
@@ -34703,7 +34849,6 @@ const useUsers = () => {
34703
34849
  }
34704
34850
  try {
34705
34851
  const result = await sdk.users.toggleUserStatus(user);
34706
- console.log('User status toggled successfully:', result);
34707
34852
  return result;
34708
34853
  }
34709
34854
  catch (error) {
@@ -34731,7 +34876,6 @@ const useUserStatus = () => {
34731
34876
  }
34732
34877
  try {
34733
34878
  const result = await sdk.userStatus.getUserStatusTypes();
34734
- console.log('User status types fetched successfully:', result);
34735
34879
  return result;
34736
34880
  }
34737
34881
  catch (error) {
@@ -34748,7 +34892,6 @@ const useUserStatus = () => {
34748
34892
  }
34749
34893
  try {
34750
34894
  const result = await sdk.userStatus.getEarnedUserStatus();
34751
- console.log('Earned user status fetched successfully:', result);
34752
34895
  return result;
34753
34896
  }
34754
34897
  catch (error) {
@@ -34763,7 +34906,6 @@ const useUserStatus = () => {
34763
34906
  }
34764
34907
  try {
34765
34908
  const result = await sdk.userStatus.createUserStatusType(userStatusType);
34766
- console.log('User status type created successfully:', result);
34767
34909
  return result;
34768
34910
  }
34769
34911
  catch (error) {
@@ -34843,7 +34985,6 @@ const useFiles = () => {
34843
34985
  }
34844
34986
  try {
34845
34987
  const result = await sdk.files.getSignedPutUrl(entityId, entityType, fileExtension);
34846
- console.log('Signed put URL generated successfully:', result);
34847
34988
  return result;
34848
34989
  }
34849
34990
  catch (error) {
@@ -34873,7 +35014,6 @@ const useFiles = () => {
34873
35014
  }
34874
35015
  try {
34875
35016
  const result = await sdk.files.getSignedGetUrl(entityId, entityType, expireSeconds);
34876
- console.log('Signed get URL generated successfully:', result);
34877
35017
  return result;
34878
35018
  }
34879
35019
  catch (error) {
@@ -34887,7 +35027,6 @@ const useFiles = () => {
34887
35027
  }
34888
35028
  try {
34889
35029
  const result = await sdk.files.getSignedUrl(request);
34890
- console.log('Signed URL generated successfully:', result);
34891
35030
  return result;
34892
35031
  }
34893
35032
  catch (error) {
@@ -34901,7 +35040,6 @@ const useFiles = () => {
34901
35040
  }
34902
35041
  try {
34903
35042
  const result = await sdk.files.optimizeMedia(url, width, height);
34904
- console.log('Media optimized successfully:', result);
34905
35043
  return result;
34906
35044
  }
34907
35045
  catch (error) {
@@ -34976,7 +35114,6 @@ const useAnalytics = () => {
34976
35114
  }
34977
35115
  try {
34978
35116
  const result = await sdk.analytics.getTransactionAnalytics(request);
34979
- console.log('Transaction analytics fetched successfully:', result);
34980
35117
  return result;
34981
35118
  }
34982
35119
  catch (error) {
@@ -35037,7 +35174,6 @@ const useDonations = () => {
35037
35174
  }
35038
35175
  try {
35039
35176
  const result = await sdk.donations.getDonationTypes();
35040
- console.log('Donation types fetched successfully:', result);
35041
35177
  return result;
35042
35178
  }
35043
35179
  catch (error) {
@@ -35059,6 +35195,7 @@ exports.PersSDKProvider = PersSDKProvider;
35059
35195
  exports.ReactNativeDPoPProvider = ReactNativeDPoPProvider;
35060
35196
  exports.ReactNativeHttpClient = ReactNativeHttpClient;
35061
35197
  exports.ReactNativeSecureStorage = ReactNativeSecureStorage;
35198
+ exports.SigningStatus = SigningStatus;
35062
35199
  exports.TRANSACTION_FORMATS = TRANSACTION_FORMATS;
35063
35200
  exports.TRANSACTION_FORMAT_DESCRIPTIONS = TRANSACTION_FORMAT_DESCRIPTIONS;
35064
35201
  exports.apiPublicKeyTestPrefix = apiPublicKeyTestPrefix;