@explorins/pers-sdk-react-native 2.1.20 → 2.1.21

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.
@@ -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;;;;;;;;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,CAqOA,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,CA6NA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
@@ -72,13 +72,6 @@ export const PersSDKProvider = ({ children, config }) => {
72
72
  if (Platform.OS !== 'web' && isDpopEnabled && !dpopSettings.cryptoProvider) {
73
73
  dpopSettings.cryptoProvider = new ReactNativeDPoPProvider();
74
74
  }
75
- // Log DPoP settings before creating auth provider
76
- console.log('[PersSDKProvider] DPoP settings:', {
77
- platform: Platform.OS,
78
- isDpopEnabled,
79
- hasCryptoProvider: !!dpopSettings.cryptoProvider,
80
- cryptoProviderType: dpopSettings.cryptoProvider?.constructor?.name || 'none'
81
- });
82
75
  // Create platform-aware auth provider if not provided
83
76
  let authProvider;
84
77
  if (config.authProvider) {
@@ -1 +1 @@
1
- {"version":3,"file":"react-native-auth-provider.d.ts","sourceRoot":"","sources":["../../src/providers/react-native-auth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAmD,MAAM,0BAA0B,CAAC;AAElI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAc7D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,oCAAoC;IACpC,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,cAAc,CAAC,EAAE,OAAO,0BAA0B,EAAE,kBAAkB,CAAC;KACxE,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,qBAA0B,GACjC,mBAAmB,CA4DrB"}
1
+ {"version":3,"file":"react-native-auth-provider.d.ts","sourceRoot":"","sources":["../../src/providers/react-native-auth-provider.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAmD,MAAM,0BAA0B,CAAC;AAElI,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAc7D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,0CAA0C;IAC1C,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,oCAAoC;IACpC,IAAI,CAAC,EAAE;QACL,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,cAAc,CAAC,EAAE,OAAO,0BAA0B,EAAE,kBAAkB,CAAC;KACxE,CAAC;CACH;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,MAAM,EAClB,MAAM,GAAE,qBAA0B,GACjC,mBAAmB,CAkDrB"}
@@ -63,15 +63,6 @@ export function createReactNativeAuthProvider(projectKey, config = {}) {
63
63
  enabled: dpop.enabled ?? true,
64
64
  cryptoProvider: dpop.cryptoProvider
65
65
  } : undefined;
66
- // Always log DPoP config for debugging (critical for mobile auth)
67
- console.log('[ReactNativeAuthProvider] Config:', {
68
- platform: Platform.OS,
69
- isWebPlatform,
70
- dpopEnabled: dpopConfig?.enabled ?? false,
71
- hasCryptoProvider: !!dpopConfig?.cryptoProvider,
72
- cryptoProviderType: dpopConfig?.cryptoProvider?.constructor?.name || 'none',
73
- storageType: tokenStorage.constructor.name
74
- });
75
66
  // Return DefaultAuthProvider configured with platform-appropriate storage
76
67
  return new DefaultAuthProvider({
77
68
  authType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorins/pers-sdk-react-native",
3
- "version": "2.1.20",
3
+ "version": "2.1.21",
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": "file:.yalc/@explorins/pers-sdk",
40
+ "@explorins/pers-sdk": "^2.1.31",
41
41
  "@explorins/pers-signer": "^1.0.33",
42
42
  "buffer": "^6.0.3",
43
43
  "ethers": "^6.15.0",
@@ -8,6 +8,7 @@ export { useBusiness } from './useBusiness';
8
8
  export { useCampaigns } from './useCampaigns';
9
9
  export { useRedemptions } from './useRedemptions';
10
10
  export { useWeb3 } from './useWeb3';
11
+ export { useResolvedUrl, useMetadata, useIPFSUrl } from './useIPFSUrl';
11
12
  export { usePurchases } from './usePurchases';
12
13
  export { useTenants } from './useTenants';
13
14
  export { useUsers } from './useUsers';
@@ -0,0 +1,139 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useWeb3 } from './useWeb3';
3
+ import type { TokenMetadata } from '@explorins/pers-sdk/web3';
4
+
5
+ /**
6
+ * React hook for resolving media URLs (IPFS or HTTPS).
7
+ *
8
+ * Automatically handles IPFS URLs by resolving them to HTTPS via tenant's gateway.
9
+ * Non-IPFS URLs are returned as-is. Handles loading and error states.
10
+ *
11
+ * @param url - The URL to resolve (can be ipfs://, https://, or undefined)
12
+ * @returns Object with resolved URL, loading state, and error
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * function NFTImage({ metadataUri }: { metadataUri?: string }) {
17
+ * const { url, isLoading } = useResolvedUrl(metadataUri);
18
+ *
19
+ * if (isLoading) return <ActivityIndicator />;
20
+ * return <Image source={{ uri: url }} />;
21
+ * }
22
+ * ```
23
+ */
24
+ export function useResolvedUrl(url: string | undefined | null) {
25
+ const { resolveIPFSUrl, isAvailable } = useWeb3();
26
+ const [resolvedUrl, setResolvedUrl] = useState<string | null>(null);
27
+ const [isLoading, setIsLoading] = useState(false);
28
+ const [error, setError] = useState<string | null>(null);
29
+
30
+ useEffect(() => {
31
+ if (!url || !isAvailable) {
32
+ setResolvedUrl(null);
33
+ return;
34
+ }
35
+
36
+ // Non-IPFS URLs don't need resolution
37
+ if (!url.startsWith('ipfs://')) {
38
+ setResolvedUrl(url);
39
+ return;
40
+ }
41
+
42
+ setIsLoading(true);
43
+ setError(null);
44
+
45
+ resolveIPFSUrl(url)
46
+ .then((resolved) => {
47
+ setResolvedUrl(resolved);
48
+ })
49
+ .catch((err) => {
50
+ setError(err instanceof Error ? err.message : 'Failed to resolve URL');
51
+ setResolvedUrl(null);
52
+ })
53
+ .finally(() => {
54
+ setIsLoading(false);
55
+ });
56
+ }, [url, isAvailable, resolveIPFSUrl]);
57
+
58
+ return {
59
+ /** Resolved HTTPS URL (or original if not IPFS) */
60
+ url: resolvedUrl,
61
+ /** Whether resolution is in progress */
62
+ isLoading,
63
+ /** Error message if resolution failed */
64
+ error,
65
+ };
66
+ }
67
+
68
+ /**
69
+ * React hook for fetching NFT/token metadata from a URI.
70
+ *
71
+ * Handles IPFS resolution automatically and returns parsed metadata
72
+ * with all nested IPFS URLs already resolved to HTTPS.
73
+ *
74
+ * @param metadataUri - The metadata URI to fetch (can be ipfs:// or https://)
75
+ * @returns Object with metadata, loading state, error, and refresh function
76
+ *
77
+ * @example
78
+ * ```tsx
79
+ * function NFTDetails({ metadataUri }: { metadataUri?: string }) {
80
+ * const { metadata, isLoading, error } = useMetadata(metadataUri);
81
+ *
82
+ * if (isLoading) return <ActivityIndicator />;
83
+ * if (error) return <Text>Error: {error}</Text>;
84
+ * if (!metadata) return null;
85
+ *
86
+ * return (
87
+ * <View>
88
+ * <Image source={{ uri: metadata.imageUrl }} />
89
+ * <Text>{metadata.name}</Text>
90
+ * <Text>{metadata.description}</Text>
91
+ * </View>
92
+ * );
93
+ * }
94
+ * ```
95
+ */
96
+ export function useMetadata(metadataUri: string | undefined | null) {
97
+ const { fetchAndProcessMetadata, isAvailable } = useWeb3();
98
+ const [metadata, setMetadata] = useState<TokenMetadata | null>(null);
99
+ const [isLoading, setIsLoading] = useState(false);
100
+ const [error, setError] = useState<string | null>(null);
101
+
102
+ const fetchMetadata = async () => {
103
+ if (!metadataUri || !isAvailable) {
104
+ setMetadata(null);
105
+ return;
106
+ }
107
+
108
+ setIsLoading(true);
109
+ setError(null);
110
+
111
+ try {
112
+ const result = await fetchAndProcessMetadata(metadataUri);
113
+ setMetadata(result);
114
+ } catch (err) {
115
+ setError(err instanceof Error ? err.message : 'Failed to fetch metadata');
116
+ setMetadata(null);
117
+ } finally {
118
+ setIsLoading(false);
119
+ }
120
+ };
121
+
122
+ useEffect(() => {
123
+ fetchMetadata();
124
+ }, [metadataUri, isAvailable]);
125
+
126
+ return {
127
+ /** Parsed metadata with resolved IPFS URLs (imageUrl, animationUrl, etc.) */
128
+ metadata,
129
+ /** Whether fetch is in progress */
130
+ isLoading,
131
+ /** Error message if fetch failed */
132
+ error,
133
+ /** Manually refresh metadata */
134
+ refresh: fetchMetadata,
135
+ };
136
+ }
137
+
138
+ // Re-export with descriptive aliases
139
+ export { useResolvedUrl as useIPFSUrl };
@@ -157,8 +157,7 @@ export const useTransactions = () => {
157
157
  }
158
158
 
159
159
  try {
160
- const result = await sdk.transactions.getTransactionById(transactionId, include);
161
- return result;
160
+ return await sdk.transactions.getTransactionById(transactionId, include);
162
161
  } catch (error) {
163
162
  console.error('Failed to fetch transaction:', error);
164
163
  throw error;
@@ -205,14 +204,12 @@ export const useTransactions = () => {
205
204
  const getUserTransactionHistory = useCallback(async (
206
205
  options?: TransactionQueryOptions
207
206
  ): Promise<PaginatedResponseDTO<TransactionDTO>> => {
208
-
209
207
  if (!isInitialized || !sdk) {
210
208
  throw new Error('SDK not initialized. Call initialize() first.');
211
209
  }
212
210
 
213
211
  try {
214
- const result = await sdk.transactions.getUserTransactionHistory(options);
215
- return result;
212
+ return await sdk.transactions.getUserTransactionHistory(options);
216
213
  } catch (error) {
217
214
  console.error('Failed to fetch transaction history:', error);
218
215
  throw error;
@@ -166,23 +166,32 @@ export const useWeb3 = () => {
166
166
  /**
167
167
  * Resolve IPFS URL to HTTP gateway URL
168
168
  *
169
- * @deprecated Use `sdk.tenant.resolveIPFSUrl()` directly - IPFS is chain-agnostic
169
+ * Converts an ipfs:// URL to an HTTPS URL using the tenant's configured IPFS gateway.
170
+ * Non-IPFS URLs are returned unchanged.
171
+ *
170
172
  * @param url - IPFS URL to resolve (ipfs://...)
171
173
  * @returns Promise resolving to HTTP gateway URL
174
+ *
175
+ * @example
176
+ * ```typescript
177
+ * const { resolveIPFSUrl } = useWeb3();
178
+ * const httpsUrl = await resolveIPFSUrl('ipfs://QmHash...');
179
+ * // Returns: 'https://gateway.pinata.cloud/ipfs/QmHash...'
180
+ * ```
172
181
  */
173
182
  const resolveIPFSUrl = useCallback(async (url: string): Promise<string> => {
174
- if (!isInitialized || !sdk) {
183
+ if (!isInitialized || !web3) {
175
184
  throw new Error('SDK not initialized. Call initialize() first.');
176
185
  }
177
186
 
178
187
  try {
179
- const result = await sdk.tenants.resolveIPFSUrl(url);
188
+ const result = await web3.resolveIPFSUrl(url);
180
189
  return result;
181
190
  } catch (error) {
182
191
  console.error('Failed to resolve IPFS URL:', error);
183
192
  throw error;
184
193
  }
185
- }, [sdk, isInitialized]);
194
+ }, [web3, isInitialized]);
186
195
 
187
196
  /**
188
197
  * Fetch and process token metadata from a URI
@@ -135,14 +135,6 @@ export const PersSDKProvider: React.FC<{
135
135
  dpopSettings.cryptoProvider = new ReactNativeDPoPProvider();
136
136
  }
137
137
 
138
- // Log DPoP settings before creating auth provider
139
- console.log('[PersSDKProvider] DPoP settings:', {
140
- platform: Platform.OS,
141
- isDpopEnabled,
142
- hasCryptoProvider: !!dpopSettings.cryptoProvider,
143
- cryptoProviderType: dpopSettings.cryptoProvider?.constructor?.name || 'none'
144
- });
145
-
146
138
  // Create platform-aware auth provider if not provided
147
139
  let authProvider: DefaultAuthProvider;
148
140
  if (config.authProvider) {
@@ -98,16 +98,6 @@ export function createReactNativeAuthProvider(
98
98
  enabled: dpop.enabled ?? true,
99
99
  cryptoProvider: dpop.cryptoProvider
100
100
  } : undefined;
101
-
102
- // Always log DPoP config for debugging (critical for mobile auth)
103
- console.log('[ReactNativeAuthProvider] Config:', {
104
- platform: Platform.OS,
105
- isWebPlatform,
106
- dpopEnabled: dpopConfig?.enabled ?? false,
107
- hasCryptoProvider: !!dpopConfig?.cryptoProvider,
108
- cryptoProviderType: dpopConfig?.cryptoProvider?.constructor?.name || 'none',
109
- storageType: tokenStorage.constructor.name
110
- });
111
101
 
112
102
  // Return DefaultAuthProvider configured with platform-appropriate storage
113
103
  return new DefaultAuthProvider({