@explorins/pers-sdk-react-native 2.1.12 → 2.1.14-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -48,15 +48,110 @@ The SDK automatically installs the following native libraries. **You must rebuil
48
48
  npm install react-native-url-polyfill
49
49
  ```
50
50
 
51
+ ### Metro Configuration (Required)
52
+
53
+ The PERS SDK uses subpath exports (`@explorins/pers-sdk/core`, etc.) which require Metro to be configured. Add to your `metro.config.js`:
54
+
55
+ ```javascript
56
+ const { getDefaultConfig } = require('expo/metro-config');
57
+ // or for bare RN: const { getDefaultConfig } = require('@react-native/metro-config');
58
+
59
+ const config = getDefaultConfig(__dirname);
60
+
61
+ // REQUIRED: Enable package exports for PERS SDK subpath imports
62
+ config.resolver.unstable_enablePackageExports = true;
63
+
64
+ module.exports = config;
65
+ ```
66
+
67
+ ---
68
+
69
+ ## ⚠️ Android Architecture Requirements
70
+
71
+ **The SDK requires React Native New Architecture** starting from v2.1.x.
72
+
73
+ ### Why?
74
+
75
+ `react-native-quick-crypto` v1.0+ (used for high-performance cryptographic operations) uses [Nitro Modules](https://github.com/margelo/nitro), which require New Architecture.
76
+
77
+ ### Quick Check
78
+
79
+ If you see errors like:
80
+ ```
81
+ NitroModulesProxy.createHybridObject(...) threw an unknown std::runtime_error
82
+ ```
83
+
84
+ Your app is running with **Old Architecture** (`newArchEnabled=false`).
85
+
86
+ ### Solution 1: Enable New Architecture (Recommended)
87
+
88
+ React Native 0.76+ has stable New Architecture support. Enable it in `android/gradle.properties`:
89
+
90
+ ```properties
91
+ # android/gradle.properties
92
+
93
+ # Use this property to enable support to the new architecture.
94
+ newArchEnabled=true
95
+
96
+ # Use this property to enable or disable the Hermes JS engine.
97
+ hermesEnabled=true
98
+ ```
99
+
100
+ Then clean and rebuild:
101
+
102
+ ```bash
103
+ cd android && ./gradlew clean && cd ..
104
+ npx react-native start --reset-cache
105
+ npx react-native run-android
106
+ ```
107
+
108
+ > **Reference**: See the [VQ Demo App's gradle.properties](https://github.com/explorins/vq-pers-integration-demo/blob/main/android/gradle.properties) for a working configuration with Expo SDK 54 and React Native 0.81.5.
109
+
110
+ ### Solution 2: Downgrade quick-crypto (For Old Architecture)
111
+
112
+ If you must stay on Old Architecture, pin to v0.7.x:
113
+
114
+ ```json
115
+ {
116
+ "resolutions": {
117
+ "react-native-quick-crypto": "0.7.17"
118
+ }
119
+ }
120
+ ```
121
+
122
+ Or for npm (in `package.json`):
123
+
124
+ ```json
125
+ {
126
+ "overrides": {
127
+ "react-native-quick-crypto": "0.7.17"
128
+ }
129
+ }
130
+ ```
131
+
132
+ ### Compatibility Matrix
133
+
134
+ | RN Version | Architecture | quick-crypto | Status |
135
+ |------------|--------------|--------------|--------|
136
+ | 0.76+ | New (`newArchEnabled=true`) | 1.0.6+ | ✅ Recommended |
137
+ | 0.76+ | Old (`newArchEnabled=false`) | 0.7.17 | ⚠️ Requires downgrade |
138
+ | < 0.76 | Old | 0.7.x | ⚠️ Use older quick-crypto |
139
+
140
+ > **See [Android Compatibility FAQ](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/docs/ANDROID_COMPATIBILITY_FAQ.md)** for detailed troubleshooting.
141
+
142
+ ---
51
143
 
52
144
  ## Critical Setup Requirement: Passkeys
53
145
 
54
- To enable Passkey authentication (WebAuthn) on iOS and Android, you **must** complete the setup in **[REACT_NATIVE_PASSKEY_SETUP.md](./REACT_NATIVE_PASSKEY_SETUP.md)**.
146
+ To enable Passkey authentication (WebAuthn) on iOS and Android, you **must**:
147
+
148
+ 1. **Register your app with PERS backend** - Contact **support@explorins.com** with:
149
+ - iOS: Bundle ID + Apple Team ID
150
+ - Android: Package Name + SHA-256 fingerprint
151
+
152
+ 2. **Configure native files** - See [Passkey Setup Guide](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/REACT_NATIVE_PASSKEY_SETUP.md)
55
153
 
56
- This includes:
57
- - Registering your app with the PERS backend (required for OS trust)
58
- - Native configuration (Info.plist, AndroidManifest.xml)
59
- - Expo/development build setup
154
+ 3. **For Expo**: Use development builds (`npx expo run:android`), not Expo Go
60
155
 
61
156
  ## Quick Start
62
157
 
@@ -1027,16 +1122,15 @@ const tokens = (await getTokens()).data;
1027
1122
 
1028
1123
  ## Documentation
1029
1124
 
1030
- ### Core Guides
1031
- - **[AUTH_STATE_HANDLING.md](./docs/AUTH_STATE_HANDLING.md)** - Comprehensive guide for handling authentication state changes
1032
- - Pattern examples for observing `isAuthenticated` state
1033
- - Custom UI for session expiration
1034
- - Platform-specific details (iOS Keychain, Android Keystore, Web)
1035
- - Best practices for auth state observation
1125
+ All documentation is available on GitHub:
1036
1126
 
1037
- ### Setup & Configuration
1038
- - **[REACT_NATIVE_PASSKEY_SETUP.md](./REACT_NATIVE_PASSKEY_SETUP.md)** - Required setup for WebAuthn/Passkey authentication
1039
- - **[DPOP_IMPLEMENTATION_GUIDE.md](./DPOP_IMPLEMENTATION_GUIDE.md)** - DPoP security implementation details
1127
+ | Guide | Description |
1128
+ |-------|-------------|
1129
+ | [Quick Setup Guide](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/docs/QUICK_SETUP_GUIDE.md) | Android + Passkey setup in one page |
1130
+ | [Passkey Setup](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/REACT_NATIVE_PASSKEY_SETUP.md) | WebAuthn/Passkey configuration |
1131
+ | [Android Compatibility](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/docs/ANDROID_COMPATIBILITY_FAQ.md) | New Architecture troubleshooting |
1132
+ | [Auth State Handling](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/docs/AUTH_STATE_HANDLING.md) | Session management patterns |
1133
+ | [Changelog](https://github.com/eXplorins/pers-sdk/blob/main/packages/pers-sdk-react-native/CHANGELOG.md) | Version history |
1040
1134
 
1041
1135
  ---
1042
1136
 
@@ -21,7 +21,7 @@ export type { TransactionSignerHook, SubmissionResult, AuthenticatedUser, Transa
21
21
  export type { AccountOwnedTokensResult, Web3Hook } from './useWeb3';
22
22
  export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } from './useEvents';
23
23
  export type { TokenBalanceWithToken, UseTokenBalancesOptions, UseTokenBalancesResult } from './useTokenBalances';
24
- export type { CampaignClaimFilters, CampaignHook } from './useCampaigns';
24
+ export type { CampaignClaimFilters, CampaignHook, GetCampaignsOptions } from './useCampaigns';
25
25
  export type { RedemptionRedeemFilters, RedemptionHook } from './useRedemptions';
26
26
  export type { TransactionQueryOptions, TransactionHook } from './useTransactions';
27
27
  export type { TriggerSourceQueryOptions, TriggerSourceHook } from './useTriggerSources';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjG,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGzE,YAAY,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGhF,YAAY,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGlF,YAAY,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,YAAY,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,IAAI,iBAAiB,EACnC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACjG,YAAY,EACV,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG9F,YAAY,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGhF,YAAY,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGlF,YAAY,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
@@ -7,6 +7,8 @@ export type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
7
7
  export interface GetCampaignsOptions {
8
8
  /** Filter by tag */
9
9
  tag?: string;
10
+ /** Free text search across name and description (case-insensitive) */
11
+ search?: string;
10
12
  /** Filter by business ID */
11
13
  businessId?: string;
12
14
  /** Page number (1-indexed) */
@@ -1 +1 @@
1
- {"version":3,"file":"useCampaigns.d.ts","sourceRoot":"","sources":["../../src/hooks/useCampaigns.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,SAAS,EACV,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;IAC5C,iBAAiB;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACrC;AAED,eAAO,MAAM,YAAY;mCA6BX,mBAAmB,KAC5B,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCAgC/B,MAAM,YACR,uBAAuB,EAAE,KAClC,QAAQ,WAAW,GAAG,IAAI,CAAC;6BAcoB,uBAAuB,KAAG,QAAQ,gBAAgB,GAAG,IAAI,CAAC;8BAmCzD;QACjD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,4BAA4B,EAAE,CAAC;KAC1C,KAAG,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;+BAkBD,QAAQ,qBAAqB,kBAAkB,CAAC,CAAC;gCA0CvF,mBAAmB,GAAG;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KACnD,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCA+BjC,oBAAoB,YACpB,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;wCAsBxC,MAAM,YACJ,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;gDAsBpC,MAAM,YACR,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;sCA4CpC,MAAM,mBACD,MAAM,KACtB,QAAQ,WAAW,CAAC;sCA4BT,MAAM,mBACD,MAAM,KACtB,QAAQ,WAAW,CAAC;;CA+BxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
1
+ {"version":3,"file":"useCampaigns.d.ts","sourceRoot":"","sources":["../../src/hooks/useCampaigns.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,uBAAuB,EACvB,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,4BAA4B,EAC5B,uBAAuB,EACvB,SAAS,EAEV,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAGzE,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oBAAoB;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qBAAqB;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC;IAC5C,iBAAiB;IACjB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,uBAAuB,EAAE,CAAC;CACrC;AAED,eAAO,MAAM,YAAY;mCA6BX,mBAAmB,KAC5B,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCAgC/B,MAAM,YACR,uBAAuB,EAAE,KAClC,QAAQ,WAAW,GAAG,IAAI,CAAC;6BAuEoB,uBAAuB,KAAG,QAAQ,gBAAgB,GAAG,IAAI,CAAC;8BAmCzD;QACjD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,OAAO,CAAC,EAAE,4BAA4B,EAAE,CAAC;KAC1C,KAAG,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;+BAkBD,QAAQ,qBAAqB,kBAAkB,CAAC,CAAC;gCA0CvF,mBAAmB,GAAG;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KACnD,QAAQ,qBAAqB,WAAW,CAAC,CAAC;kCA+BjC,oBAAoB,YACpB,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;wCAsBxC,MAAM,YACJ,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;gDAsBpC,MAAM,YACR,4BAA4B,EAAE,KACvC,QAAQ,qBAAqB,gBAAgB,CAAC,CAAC;sCA4CpC,MAAM,mBACD,MAAM,KACtB,QAAQ,WAAW,CAAC;sCA4BT,MAAM,mBACD,MAAM,KACtB,QAAQ,WAAW,CAAC;;CA+BxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC"}
@@ -70,6 +70,63 @@ export const useCampaigns = () => {
70
70
  throw error;
71
71
  }
72
72
  }, [sdk, isInitialized]);
73
+ /**
74
+ * Claim a campaign reward with optional dynamic context
75
+ *
76
+ * Triggers a campaign claim for the authenticated user. The campaign must be active
77
+ * and the user must meet all eligibility requirements. Supports dynamic context for
78
+ * personalized NFT generation when the campaign issues ERC721 tokens.
79
+ *
80
+ * @param request - Campaign claim request with optional context
81
+ * @param request.campaignId - ID of the campaign to claim (optional if using triggerSourceId)
82
+ * @param request.triggerSourceId - ID of trigger source (QR, NFC, etc.)
83
+ * @param request.context - Dynamic context for NFT personalization
84
+ * @param request.metadata - Additional metadata for the claim
85
+ * @param request.latitude - User's latitude for geo-validated claims
86
+ * @param request.longitude - User's longitude for geo-validated claims
87
+ * @returns Promise resolving to campaign claim result
88
+ *
89
+ * @example Basic campaign claim
90
+ * ```typescript
91
+ * const claim = await claimCampaign({
92
+ * triggerSourceId: 'qr-code-123',
93
+ * });
94
+ * ```
95
+ *
96
+ * @example Campaign claim with dynamic context (personalized NFT)
97
+ * ```typescript
98
+ * import { DynamicContext } from '@explorins/pers-sdk-react-native';
99
+ *
100
+ * const context: DynamicContext = {
101
+ * // Validity - token valid for 30 days
102
+ * validityDate: new Date().toISOString(),
103
+ * validityDuration: 30,
104
+ *
105
+ * // AI prompt context - available as {{context.xxx}} in prompts
106
+ * visitorName: 'John Doe',
107
+ * visitLocation: 'Grand Hotel Lobby',
108
+ * membershipTier: 'Gold',
109
+ * };
110
+ *
111
+ * const claim = await claimCampaign({
112
+ * triggerSourceId: 'hotel-checkin-qr',
113
+ * context,
114
+ * });
115
+ * ```
116
+ *
117
+ * @example Geo-validated claim with context
118
+ * ```typescript
119
+ * const claim = await claimCampaign({
120
+ * triggerSourceId: 'museum-entrance-nfc',
121
+ * latitude: 48.8606,
122
+ * longitude: 2.3376,
123
+ * context: {
124
+ * visitorType: 'Adult',
125
+ * ticketCategory: 'General Admission',
126
+ * }
127
+ * });
128
+ * ```
129
+ */
73
130
  const claimCampaign = useCallback(async (request) => {
74
131
  if (!isInitialized || !sdk) {
75
132
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -97,7 +154,7 @@ export const useCampaigns = () => {
97
154
  * // Get user's claims with campaign details
98
155
  * const { data: claims } = await getUserClaims({ include: ['campaign', 'business'] });
99
156
  * claims.forEach(claim => {
100
- * console.log('Campaign:', claim.included?.campaign?.title);
157
+ * console.log('Campaign:', claim.included?.campaign?.name);
101
158
  * });
102
159
  *
103
160
  * // With pagination
@@ -1,14 +1,35 @@
1
1
  import { OnStatusUpdateFn } from './useTransactionSigner';
2
- import type { RedemptionCreateRequestDTO, RedemptionDTO, RedemptionRedeemDTO, RedemptionRedeemRequestResponseDTO, RedemptionTypeDTO, PaginatedResponseDTO, RedemptionRedeemIncludeRelation } from '@explorins/pers-shared';
2
+ import type { RedemptionCreateRequestDTO, RedemptionDTO, RedemptionRedeemDTO, RedemptionRedeemRequestResponseDTO, RedemptionTypeDTO, PaginatedResponseDTO, RedemptionRedeemIncludeRelation, ProcessRecordStatus, DynamicContext, SortOrder } from '@explorins/pers-shared';
3
3
  import type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
4
4
  import type { PaginationOptions } from '@explorins/pers-sdk';
5
- export type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
5
+ export type { RedemptionRedeemFilters, RedemptionFilterOptions } from '@explorins/pers-sdk/redemption';
6
+ /**
7
+ * Options for fetching redemptions with filtering and pagination
8
+ */
9
+ export interface GetRedemptionsOptions {
10
+ /** Filter by active status (Admin only - regular users always see active offers) */
11
+ active?: boolean;
12
+ /** Free text search across name, description, tags (case-insensitive) */
13
+ search?: string;
14
+ /** Page number (1-indexed) */
15
+ page?: number;
16
+ /** Results per page */
17
+ limit?: number;
18
+ /** Field to sort by */
19
+ sortBy?: 'name' | 'createdAt';
20
+ /** Sort direction */
21
+ sortOrder?: SortOrder;
22
+ }
6
23
  export declare const useRedemptions: () => {
7
- getRedemptions: (options?: {
8
- active?: boolean;
9
- }) => Promise<PaginatedResponseDTO<RedemptionDTO>>;
10
- getUserRedemptions: (options?: PaginationOptions, include?: RedemptionRedeemIncludeRelation[]) => Promise<PaginatedResponseDTO<RedemptionRedeemDTO>>;
11
- redeem: (redemptionId: string, onStatusUpdate?: OnStatusUpdateFn) => Promise<RedemptionRedeemRequestResponseDTO>;
24
+ getRedemptions: (options?: GetRedemptionsOptions) => Promise<PaginatedResponseDTO<RedemptionDTO>>;
25
+ getUserRedemptions: (filters?: {
26
+ redemptionId?: string;
27
+ status?: ProcessRecordStatus;
28
+ }, options?: PaginationOptions, include?: RedemptionRedeemIncludeRelation[]) => Promise<PaginatedResponseDTO<RedemptionRedeemDTO>>;
29
+ redeem: (redemptionId: string, options?: {
30
+ context?: DynamicContext;
31
+ onStatusUpdate?: OnStatusUpdateFn;
32
+ }) => Promise<RedemptionRedeemRequestResponseDTO>;
12
33
  getRedemptionTypes: () => Promise<PaginatedResponseDTO<RedemptionTypeDTO>>;
13
34
  getRedemptionRedeems: (filters?: RedemptionRedeemFilters, include?: RedemptionRedeemIncludeRelation[]) => Promise<PaginatedResponseDTO<RedemptionRedeemDTO>>;
14
35
  createRedemption: (redemptionData: RedemptionCreateRequestDTO) => Promise<RedemptionDTO>;
@@ -1 +1 @@
1
- {"version":3,"file":"useRedemptions.d.ts","sourceRoot":"","sources":["../../src/hooks/useRedemptions.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0C,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,kCAAkC,EAClC,iBAAiB,EACjB,oBAAoB,EACpB,+BAA+B,EAChC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAE9E,eAAO,MAAM,cAAc;+BAY2B;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,KAAG,QAAQ,qBAAqB,aAAa,CAAC,CAAC;mCAoC3G,iBAAiB,YACjB,+BAA+B,EAAE,KAC1C,QAAQ,qBAAqB,mBAAmB,CAAC,CAAC;2BAkBL,MAAM,mBAAmB,gBAAgB,KAAG,QAAQ,kCAAkC,CAAC;8BAmGtF,QAAQ,qBAAqB,iBAAiB,CAAC,CAAC;qCA9BrF,uBAAuB,YACvB,+BAA+B,EAAE,KAC1C,QAAQ,qBAAqB,mBAAmB,CAAC,CAAC;uCAcO,0BAA0B,KAAG,QAAQ,aAAa,CAAC;qCA4BrD,MAAM,kBAAkB,0BAA0B,KAAG,QAAQ,aAAa,CAAC;2CAcrE,MAAM,KAAG,QAAQ,aAAa,CAAC;;;;CA4BhG,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
1
+ {"version":3,"file":"useRedemptions.d.ts","sourceRoot":"","sources":["../../src/hooks/useRedemptions.ts"],"names":[],"mappings":"AAEA,OAAO,EAA0C,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,KAAK,EACV,0BAA0B,EAC1B,aAAa,EACb,mBAAmB,EACnB,kCAAkC,EAClC,iBAAiB,EACjB,oBAAoB,EACpB,+BAA+B,EAC/B,mBAAmB,EACnB,cAAc,EACd,SAAS,EACV,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,uBAAuB,EAA2B,MAAM,gCAAgC,CAAC;AACvG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAG7D,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAEvG;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oFAAoF;IACpF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uBAAuB;IACvB,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC9B,qBAAqB;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,eAAO,MAAM,cAAc;+BAyC2B,qBAAqB,KAAG,QAAQ,qBAAqB,aAAa,CAAC,CAAC;mCAyC5G;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,mBAAmB,CAAA;KAAE,YACvD,iBAAiB,YACjB,+BAA+B,EAAE,KAC1C,QAAQ,qBAAqB,mBAAmB,CAAC,CAAC;2BAkErC,MAAM,YACV;QAAE,OAAO,CAAC,EAAE,cAAc,CAAC;QAAC,cAAc,CAAC,EAAE,gBAAgB,CAAA;KAAE,KACxE,QAAQ,kCAAkC,CAAC;8BAmGG,QAAQ,qBAAqB,iBAAiB,CAAC,CAAC;qCA9BrF,uBAAuB,YACvB,+BAA+B,EAAE,KAC1C,QAAQ,qBAAqB,mBAAmB,CAAC,CAAC;uCAcO,0BAA0B,KAAG,QAAQ,aAAa,CAAC;qCA4BrD,MAAM,kBAAkB,0BAA0B,KAAG,QAAQ,aAAa,CAAC;2CAcrE,MAAM,KAAG,QAAQ,aAAa,CAAC;;;;CA4BhG,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -11,6 +11,35 @@ export const useRedemptions = () => {
11
11
  * **Administrators:** Can see all redemptions and filter by active/inactive status
12
12
  *
13
13
  * The backend enforces permission-based filtering automatically.
14
+ *
15
+ * @param options - Filter and pagination options
16
+ * @param options.active - Filter by active status (Admin only)
17
+ * @param options.search - Free text search across name, description, tags
18
+ * @param options.page - Page number (1-indexed)
19
+ * @param options.limit - Results per page
20
+ * @param options.sortBy - Field to sort by ('name' | 'createdAt')
21
+ * @param options.sortOrder - Sort direction ('ASC' | 'DESC')
22
+ *
23
+ * @example Basic usage
24
+ * ```typescript
25
+ * const { data: offers } = await getRedemptions();
26
+ * ```
27
+ *
28
+ * @example Search redemptions
29
+ * ```typescript
30
+ * const { data: coffeeOffers } = await getRedemptions({ search: 'coffee' });
31
+ * ```
32
+ *
33
+ * @example With pagination and sorting
34
+ * ```typescript
35
+ * const { data, pagination } = await getRedemptions({
36
+ * search: 'discount',
37
+ * page: 1,
38
+ * limit: 10,
39
+ * sortBy: 'name',
40
+ * sortOrder: 'ASC'
41
+ * });
42
+ * ```
14
43
  */
15
44
  const getRedemptions = useCallback(async (options) => {
16
45
  if (!isInitialized || !sdk) {
@@ -26,27 +55,32 @@ export const useRedemptions = () => {
26
55
  }
27
56
  }, [sdk, isInitialized]);
28
57
  /**
29
- * Get user's redemption history with optional pagination and include relations
58
+ * Get user's redemption history with optional filters, pagination and include relations
30
59
  *
60
+ * @param filters - Optional filters (redemptionId, status)
31
61
  * @param options - Pagination options (page, limit, sortBy, sortOrder)
32
- * @param include - Relations to include: 'redemption', 'user', 'business'
62
+ * @param include - Relations to include: 'redemption', 'user', 'business', 'transactions'
33
63
  * @returns Promise resolving to paginated redemption history
34
64
  *
35
65
  * @example
36
66
  * ```typescript
37
67
  * // Get first page of user redemptions
38
- * const { data: redeems, pagination } = await getUserRedemptions({ page: 1, limit: 10 });
68
+ * const { data: redeems, pagination } = await getUserRedemptions({}, { page: 1, limit: 10 });
39
69
  * console.log(`Page ${pagination.page} of ${pagination.pages}`);
40
70
  *
71
+ * // Get only completed redemptions
72
+ * import { ProcessRecordStatus } from '@explorins/pers-shared';
73
+ * const { data: completed } = await getUserRedemptions({ status: ProcessRecordStatus.COMPLETED });
74
+ *
41
75
  * // Get user redemptions with full redemption details
42
- * const { data: redeems } = await getUserRedemptions({}, ['redemption', 'business']);
76
+ * const { data: redeems } = await getUserRedemptions({}, {}, ['redemption', 'business']);
43
77
  * redeems.forEach(redeem => {
44
- * console.log('Redemption:', redeem.included?.redemption?.title);
78
+ * console.log('Redemption:', redeem.included?.redemption?.name);
45
79
  * console.log('Business:', redeem.included?.business?.displayName);
46
80
  * });
47
81
  * ```
48
82
  */
49
- const getUserRedemptions = useCallback(async (options, include) => {
83
+ const getUserRedemptions = useCallback(async (filters, options, include) => {
50
84
  if (!isInitialized || !sdk) {
51
85
  throw new Error('SDK not initialized. Call initialize() first.');
52
86
  }
@@ -55,7 +89,7 @@ export const useRedemptions = () => {
55
89
  return { data: [], pagination: { page: 1, limit: 0, total: 0, pages: 0, hasNext: false, hasPrev: false } };
56
90
  }
57
91
  try {
58
- const result = await sdk.redemptions.getUserRedemptions(options, include);
92
+ const result = await sdk.redemptions.getUserRedemptions(filters, options, include);
59
93
  return result;
60
94
  }
61
95
  catch (error) {
@@ -63,7 +97,54 @@ export const useRedemptions = () => {
63
97
  throw error;
64
98
  }
65
99
  }, [sdk, isInitialized, isAuthenticated]);
66
- const redeem = useCallback(async (redemptionId, onStatusUpdate) => {
100
+ /**
101
+ * Redeem a redemption offer with optional dynamic context
102
+ *
103
+ * Supports dynamic context for personalized NFT generation when the redemption
104
+ * issues ERC721 tokens. Context can include validity dates, AI prompt placeholders,
105
+ * and custom metadata.
106
+ *
107
+ * @param redemptionId - ID of the redemption to redeem
108
+ * @param options - Optional settings
109
+ * @param options.context - Dynamic context for NFT personalization (validity dates, AI prompts)
110
+ * @param options.onStatusUpdate - Callback for transaction signing status updates
111
+ * @returns Promise resolving to redemption result
112
+ *
113
+ * @example Basic redemption
114
+ * ```typescript
115
+ * const result = await redeem('redemption-123');
116
+ * ```
117
+ *
118
+ * @example Redemption with dynamic context (personalized NFT)
119
+ * ```typescript
120
+ * const result = await redeem('event-ticket-123', {
121
+ * context: {
122
+ * // Validity - token valid for event duration
123
+ * validityDate: new Date().toISOString(),
124
+ * validityDuration: 8, // 8 hours
125
+ *
126
+ * // AI prompt context - available as {{context.xxx}} in prompts
127
+ * attendeeName: 'John Doe',
128
+ * ticketTier: 'VIP',
129
+ * seatSection: 'A12',
130
+ * }
131
+ * });
132
+ * ```
133
+ *
134
+ * @example Hotel stay NFT with check-in/check-out dates
135
+ * ```typescript
136
+ * const result = await redeem('hotel-nft-456', {
137
+ * context: {
138
+ * validityDate: '2026-04-15T14:00:00Z', // Check-in
139
+ * validityEndDate: '2026-04-20T11:00:00Z', // Check-out
140
+ * guestName: 'Jane Smith',
141
+ * roomNumber: '305',
142
+ * roomType: 'Suite',
143
+ * }
144
+ * });
145
+ * ```
146
+ */
147
+ const redeem = useCallback(async (redemptionId, options) => {
67
148
  if (!isInitialized || !sdk) {
68
149
  throw new Error('SDK not initialized. Call initialize() first.');
69
150
  }
@@ -71,11 +152,11 @@ export const useRedemptions = () => {
71
152
  throw new Error('SDK not authenticated. redeem requires authentication.');
72
153
  }
73
154
  try {
74
- const result = await sdk.redemptions.redeem(redemptionId);
155
+ const result = await sdk.redemptions.redeem(redemptionId, options?.context);
75
156
  const txToken = result.senderTransaction?.actionable?.authToken;
76
157
  if (txToken && isSignerAvailable) {
77
158
  try {
78
- const signingResult = await signAndSubmitTransactionWithJWT(txToken, onStatusUpdate);
159
+ const signingResult = await signAndSubmitTransactionWithJWT(txToken, options?.onStatusUpdate);
79
160
  if (signingResult.success) {
80
161
  // Return enhanced result with signing information
81
162
  return {
@@ -88,10 +88,17 @@ export interface UseTokenBalancesResult {
88
88
  * **Basic Usage:**
89
89
  * ```typescript
90
90
  * import { useTokenBalances, useTokens, usePersSDK } from '@explorins/pers-sdk-react-native';
91
+ * import { useState, useEffect } from 'react';
91
92
  *
92
93
  * function TokenBalancesScreen() {
93
94
  * const { user } = usePersSDK();
94
- * const { availableTokens } = useTokens();
95
+ * const { getTokens } = useTokens();
96
+ * const [availableTokens, setAvailableTokens] = useState([]);
97
+ *
98
+ * // Load tokens on mount
99
+ * useEffect(() => {
100
+ * getTokens().then(result => setAvailableTokens(result.data));
101
+ * }, []);
95
102
  *
96
103
  * // App explicitly selects which wallet to use
97
104
  * const walletAddress = user?.wallets?.[0]?.address;
@@ -1 +1 @@
1
- {"version":3,"file":"useTokenBalances.d.ts","sourceRoot":"","sources":["../../src/hooks/useTokenBalances.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,0BAA0B,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,YAAY,EAAE,YAAY,CAAC;IAC3B,8DAA8D;IAC9D,KAAK,EAAE,QAAQ,CAAC;IAChB,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0DAA0D;IAC1D,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,sFAAsF;IACtF,WAAW,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAqLzF"}
1
+ {"version":3,"file":"useTokenBalances.d.ts","sourceRoot":"","sources":["../../src/hooks/useTokenBalances.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoB,KAAK,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,0BAA0B,CAAC;AAElF;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,YAAY,EAAE,YAAY,CAAC;IAC3B,8DAA8D;IAC9D,KAAK,EAAE,QAAQ,CAAC;IAChB,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,eAAe,CAAC,EAAE,QAAQ,EAAE,CAAC;IAC7B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0DAA0D;IAC1D,aAAa,EAAE,qBAAqB,EAAE,CAAC;IACvC,6CAA6C;IAC7C,SAAS,EAAE,OAAO,CAAC;IACnB,sCAAsC;IACtC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,uCAAuC;IACvC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,sFAAsF;IACtF,WAAW,EAAE,OAAO,CAAC;IACrB,0CAA0C;IAC1C,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAqLzF"}
@@ -25,10 +25,17 @@ import { NativeTokenTypes } from '@explorins/pers-shared';
25
25
  * **Basic Usage:**
26
26
  * ```typescript
27
27
  * import { useTokenBalances, useTokens, usePersSDK } from '@explorins/pers-sdk-react-native';
28
+ * import { useState, useEffect } from 'react';
28
29
  *
29
30
  * function TokenBalancesScreen() {
30
31
  * const { user } = usePersSDK();
31
- * const { availableTokens } = useTokens();
32
+ * const { getTokens } = useTokens();
33
+ * const [availableTokens, setAvailableTokens] = useState([]);
34
+ *
35
+ * // Load tokens on mount
36
+ * useEffect(() => {
37
+ * getTokens().then(result => setAvailableTokens(result.data));
38
+ * }, []);
32
39
  *
33
40
  * // App explicitly selects which wallet to use
34
41
  * const walletAddress = user?.wallets?.[0]?.address;
@@ -1 +1 @@
1
- {"version":3,"file":"useTransactionSigner.d.ts","sourceRoot":"","sources":["../../src/hooks/useTransactionSigner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,aAAa,EAAkB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI3G,KAAK,gBAAgB,GAAG,OAAO,qCAAqC,EAAE,gBAAgB,CAAC;AACvF,KAAK,iBAAiB,GAAG,OAAO,qCAAqC,EAAE,iBAAiB,CAAC;AACzF,KAAK,wBAAwB,GAAG,OAAO,qCAAqC,EAAE,wBAAwB,CAAC;AAGvG,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAczG;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/G,mBAAmB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3G,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgLG;AACH,eAAO,MAAM,oBAAoB,QAAO,qBA2TvC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"useTransactionSigner.d.ts","sourceRoot":"","sources":["../../src/hooks/useTransactionSigner.ts"],"names":[],"mappings":"AAEA,OAAO,EAAoB,aAAa,EAAkB,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAI3G,KAAK,gBAAgB,GAAG,OAAO,qCAAqC,EAAE,gBAAgB,CAAC;AACvF,KAAK,iBAAiB,GAAG,OAAO,qCAAqC,EAAE,iBAAiB,CAAC;AACzF,KAAK,wBAAwB,GAAG,OAAO,qCAAqC,EAAE,wBAAwB,CAAC;AAGvG,OAAO,EAAE,aAAa,EAAE,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;AA4CzG;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC/G,mBAAmB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC3G,mBAAmB,EAAE,OAAO,CAAC;IAC7B,iBAAiB,EAAE,OAAO,CAAC;IAC3B,aAAa,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgLG;AACH,eAAO,MAAM,oBAAoB,QAAO,qBA4TvC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,wBAAwB,EAAE,CAAC"}
@@ -3,15 +3,41 @@ import { useCallback, useState, useRef, useEffect } from 'react';
3
3
  import { SigningStatus } from '@explorins/pers-signer';
4
4
  // Re-export signing status types from signer SDK for convenience
5
5
  export { SigningStatus };
6
- // Dynamic import the signer SDK to avoid build issues with static dependencies
7
- let createPersSignerSDK = null;
8
- try {
9
- const signerModule = require('@explorins/pers-signer/react-native');
10
- createPersSignerSDK = signerModule.createPersSignerSDK;
11
- }
12
- catch (error) {
13
- console.warn('[useTransactionSigner] PERS Signer SDK not available:', error.message);
14
- console.warn('[useTransactionSigner] Real blockchain signing will not be available');
6
+ // Lazy-loaded signer SDK factory - initialized on first use to avoid native module timing issues
7
+ let _createPersSignerSDK = null;
8
+ let _signerInitAttempted = false;
9
+ /**
10
+ * Lazily load the PERS Signer SDK.
11
+ *
12
+ * Supports customer pre-initialization via global.__PersSigner for environments
13
+ * where native module timing is unpredictable (e.g., certain React Native setups).
14
+ *
15
+ * @returns The createPersSignerSDK function or null if unavailable
16
+ */
17
+ function getSignerSDKFactory() {
18
+ if (_signerInitAttempted) {
19
+ // Already tried - return cached result (could be null if failed)
20
+ return _createPersSignerSDK;
21
+ }
22
+ _signerInitAttempted = true;
23
+ // Check for customer pre-initialized global (for native module timing issues)
24
+ if (typeof global !== 'undefined' && global.__PersSigner?.createPersSignerSDK) {
25
+ _createPersSignerSDK = global.__PersSigner.createPersSignerSDK;
26
+ return _createPersSignerSDK;
27
+ }
28
+ // Standard lazy load
29
+ try {
30
+ const signerModule = require('@explorins/pers-signer/react-native');
31
+ _createPersSignerSDK = signerModule.createPersSignerSDK;
32
+ return _createPersSignerSDK;
33
+ }
34
+ catch (error) {
35
+ console.warn('[useTransactionSigner] PERS Signer SDK not available:', error.message);
36
+ console.warn('[useTransactionSigner] Real blockchain signing will not be available');
37
+ console.warn('[useTransactionSigner] Tip: If timing issues, pre-initialize in index.js: global.__PersSigner = require("@explorins/pers-signer/react-native")');
38
+ _createPersSignerSDK = null; // Mark as unavailable
39
+ return null;
40
+ }
15
41
  }
16
42
  // Constants - TODO: Move to environment config later
17
43
  const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0954c98f287b29e";
@@ -201,6 +227,7 @@ export const useTransactionSigner = () => {
201
227
  // Auto-initialize signer SDK when PERS SDK is ready
202
228
  useEffect(() => {
203
229
  const initializeSignerSDK = async () => {
230
+ const createPersSignerSDK = getSignerSDKFactory();
204
231
  if (!createPersSignerSDK) {
205
232
  console.warn('[useTransactionSigner] Signer SDK not available');
206
233
  return;
@@ -315,7 +342,7 @@ export const useTransactionSigner = () => {
315
342
  if (!isSignerInitialized || !signerSDKRef.current) {
316
343
  throw new Error('Transaction signer not initialized');
317
344
  }
318
- if (!createPersSignerSDK) {
345
+ if (!getSignerSDKFactory()) {
319
346
  throw new Error('PERS Signer SDK not available. Blockchain signing is not supported.');
320
347
  }
321
348
  // Create status callback wrapper that updates both hook state and calls user callback
@@ -459,7 +486,7 @@ export const useTransactionSigner = () => {
459
486
  * );
460
487
  * ```
461
488
  */
462
- isSignerAvailable: isSignerInitialized && !!createPersSignerSDK,
489
+ isSignerAvailable: isSignerInitialized && !!getSignerSDKFactory(),
463
490
  /**
464
491
  * Current signing status for UI feedback
465
492
  *
package/dist/index.d.ts CHANGED
@@ -210,7 +210,7 @@ export { useAuth, useTokens, useTokenBalances, useTransactions, useTransactionSi
210
210
  export type { TransactionSignerHook, OnStatusUpdateFn, StatusUpdateData, SigningStatusType, TransactionSigningResult, SubmissionResult, AuthenticatedUser } from './hooks';
211
211
  export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } from './hooks';
212
212
  export type { TokenBalanceWithToken, UseTokenBalancesOptions, UseTokenBalancesResult } from './hooks';
213
- export type { CampaignClaimFilters, CampaignHook } from './hooks';
213
+ export type { CampaignClaimFilters, CampaignHook, GetCampaignsOptions } from './hooks';
214
214
  export type { RedemptionRedeemFilters, RedemptionHook } from './hooks';
215
215
  export type { TransactionQueryOptions, TransactionHook } from './hooks';
216
216
  export type { TriggerSourceQueryOptions, TriggerSourceHook } from './hooks';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAGH,OAAO,aAAa,CAAC;AAMrB;;;;;;;;GAQG;AACH,OAAO,EACL,6BAA6B,EAC7B,KAAK,qBAAqB,EAC3B,MAAM,wCAAwC,CAAC;AAMhD;;;;;;;;;;GAUG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAEvE;;;;;;;;GAQG;AACH,OAAO,EACL,wBAAwB,GACzB,MAAM,uCAAuC,CAAC;AAM/C;;;GAGG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAMvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EACL,eAAe,EACf,UAAU,EACV,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,6BAA6B,CAAC;AAMrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0FG;AACH,OAAO,EACL,OAAO,EACP,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,YAAY,EACZ,cAAc,EACd,OAAO,EACP,YAAY,EACZ,UAAU,EACV,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,SAAS,CAAC;AAGjB,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAG7F,YAAY,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGtG,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGlE,YAAY,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGvE,YAAY,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAGxE,YAAY,EAAE,yBAAyB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG5E,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAM7C;;;;;;;;;;GAUG;AACH,OAAO,EACL,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,sCAAsC,CAAC;AAM9C;;;;;;;;GAQG;AACH,OAAO,EACL,8BAA8B,EAC/B,MAAM,aAAa,CAAC;AAMrB;;;;;;;;;;;;;;;;GAgBG;AACH,cAAc,wBAAwB,CAAC;AAEvC;;;;GAIG;AACH,OAAO,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAC;AAE7E;;;;;GAKG;AACH,OAAO,EAEL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,YAAY,EACV,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,sBAAsB,EACvB,MAAM,0BAA0B,CAAC;AAMlC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,2BAA2B,EAC5B,MAAM,iCAAiC,CAAC;AAEzC,YAAY,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAMzG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuFG;AACH,OAAO,EACL,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACX,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}