@explorins/pers-sdk-react-native 2.1.12 → 2.1.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@explorins/pers-sdk-react-native",
3
- "version": "2.1.12",
3
+ "version": "2.1.13",
4
4
  "description": "React Native SDK for PERS Platform - Tourism Loyalty System with Blockchain Transaction Signing and WebAuthn Authentication",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -37,7 +37,7 @@
37
37
  "author": "eXplorins",
38
38
  "license": "MIT",
39
39
  "dependencies": {
40
- "@explorins/pers-sdk": "^2.1.18",
40
+ "@explorins/pers-sdk": "^2.1.20",
41
41
  "@explorins/pers-signer": "^1.0.33",
42
42
  "buffer": "^6.0.3",
43
43
  "ethers": "^6.15.0",
@@ -155,7 +155,7 @@
155
155
  "@ethersproject/scrypt": false
156
156
  },
157
157
  "devDependencies": {
158
- "@explorins/pers-shared": "^2.1.117",
158
+ "@explorins/pers-shared": "^2.1.123",
159
159
  "@react-native-async-storage/async-storage": "^3.0.2",
160
160
  "@rollup/plugin-commonjs": "^25.0.7",
161
161
  "@rollup/plugin-json": "^6.1.0",
@@ -38,7 +38,7 @@ export type {
38
38
  } from './useTokenBalances';
39
39
 
40
40
  // Export campaign-related types
41
- export type { CampaignClaimFilters, CampaignHook } from './useCampaigns';
41
+ export type { CampaignClaimFilters, CampaignHook, GetCampaignsOptions } from './useCampaigns';
42
42
 
43
43
  // Export redemption-related types
44
44
  export type { RedemptionRedeemFilters, RedemptionHook } from './useRedemptions';
@@ -8,7 +8,8 @@ import type {
8
8
  PaginatedResponseDTO,
9
9
  CampaignClaimIncludeRelation,
10
10
  CampaignIncludeRelation,
11
- SortOrder
11
+ SortOrder,
12
+ // DynamicContext
12
13
  } from '@explorins/pers-shared';
13
14
  import type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
14
15
 
@@ -113,6 +114,63 @@ export const useCampaigns = () => {
113
114
  }
114
115
  }, [sdk, isInitialized]);
115
116
 
117
+ /**
118
+ * Claim a campaign reward with optional dynamic context
119
+ *
120
+ * Triggers a campaign claim for the authenticated user. The campaign must be active
121
+ * and the user must meet all eligibility requirements. Supports dynamic context for
122
+ * personalized NFT generation when the campaign issues ERC721 tokens.
123
+ *
124
+ * @param request - Campaign claim request with optional context
125
+ * @param request.campaignId - ID of the campaign to claim (optional if using triggerSourceId)
126
+ * @param request.triggerSourceId - ID of trigger source (QR, NFC, etc.)
127
+ * @param request.context - Dynamic context for NFT personalization
128
+ * @param request.metadata - Additional metadata for the claim
129
+ * @param request.latitude - User's latitude for geo-validated claims
130
+ * @param request.longitude - User's longitude for geo-validated claims
131
+ * @returns Promise resolving to campaign claim result
132
+ *
133
+ * @example Basic campaign claim
134
+ * ```typescript
135
+ * const claim = await claimCampaign({
136
+ * triggerSourceId: 'qr-code-123',
137
+ * });
138
+ * ```
139
+ *
140
+ * @example Campaign claim with dynamic context (personalized NFT)
141
+ * ```typescript
142
+ * import { DynamicContext } from '@explorins/pers-sdk-react-native';
143
+ *
144
+ * const context: DynamicContext = {
145
+ * // Validity - token valid for 30 days
146
+ * validityDate: new Date().toISOString(),
147
+ * validityDuration: 30,
148
+ *
149
+ * // AI prompt context - available as {{context.xxx}} in prompts
150
+ * visitorName: 'John Doe',
151
+ * visitLocation: 'Grand Hotel Lobby',
152
+ * membershipTier: 'Gold',
153
+ * };
154
+ *
155
+ * const claim = await claimCampaign({
156
+ * triggerSourceId: 'hotel-checkin-qr',
157
+ * context,
158
+ * });
159
+ * ```
160
+ *
161
+ * @example Geo-validated claim with context
162
+ * ```typescript
163
+ * const claim = await claimCampaign({
164
+ * triggerSourceId: 'museum-entrance-nfc',
165
+ * latitude: 48.8606,
166
+ * longitude: 2.3376,
167
+ * context: {
168
+ * visitorType: 'Adult',
169
+ * ticketCategory: 'General Admission',
170
+ * }
171
+ * });
172
+ * ```
173
+ */
116
174
  const claimCampaign = useCallback(async (request: CampaignClaimRequestDTO): Promise<CampaignClaimDTO | null> => {
117
175
  if (!isInitialized || !sdk) {
118
176
  throw new Error('SDK not initialized. Call initialize() first.');
@@ -141,7 +199,7 @@ export const useCampaigns = () => {
141
199
  * // Get user's claims with campaign details
142
200
  * const { data: claims } = await getUserClaims({ include: ['campaign', 'business'] });
143
201
  * claims.forEach(claim => {
144
- * console.log('Campaign:', claim.included?.campaign?.title);
202
+ * console.log('Campaign:', claim.included?.campaign?.name);
145
203
  * });
146
204
  *
147
205
  * // With pagination
@@ -8,7 +8,9 @@ import type {
8
8
  RedemptionRedeemRequestResponseDTO,
9
9
  RedemptionTypeDTO,
10
10
  PaginatedResponseDTO,
11
- RedemptionRedeemIncludeRelation
11
+ RedemptionRedeemIncludeRelation,
12
+ ProcessRecordStatus,
13
+ DynamicContext
12
14
  } from '@explorins/pers-shared';
13
15
  import type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
14
16
  import type { PaginationOptions } from '@explorins/pers-sdk';
@@ -43,27 +45,33 @@ export const useRedemptions = () => {
43
45
  }, [sdk, isInitialized]);
44
46
 
45
47
  /**
46
- * Get user's redemption history with optional pagination and include relations
48
+ * Get user's redemption history with optional filters, pagination and include relations
47
49
  *
50
+ * @param filters - Optional filters (redemptionId, status)
48
51
  * @param options - Pagination options (page, limit, sortBy, sortOrder)
49
- * @param include - Relations to include: 'redemption', 'user', 'business'
52
+ * @param include - Relations to include: 'redemption', 'user', 'business', 'transactions'
50
53
  * @returns Promise resolving to paginated redemption history
51
54
  *
52
55
  * @example
53
56
  * ```typescript
54
57
  * // Get first page of user redemptions
55
- * const { data: redeems, pagination } = await getUserRedemptions({ page: 1, limit: 10 });
58
+ * const { data: redeems, pagination } = await getUserRedemptions({}, { page: 1, limit: 10 });
56
59
  * console.log(`Page ${pagination.page} of ${pagination.pages}`);
57
60
  *
61
+ * // Get only completed redemptions
62
+ * import { ProcessRecordStatus } from '@explorins/pers-shared';
63
+ * const { data: completed } = await getUserRedemptions({ status: ProcessRecordStatus.COMPLETED });
64
+ *
58
65
  * // Get user redemptions with full redemption details
59
- * const { data: redeems } = await getUserRedemptions({}, ['redemption', 'business']);
66
+ * const { data: redeems } = await getUserRedemptions({}, {}, ['redemption', 'business']);
60
67
  * redeems.forEach(redeem => {
61
- * console.log('Redemption:', redeem.included?.redemption?.title);
68
+ * console.log('Redemption:', redeem.included?.redemption?.name);
62
69
  * console.log('Business:', redeem.included?.business?.displayName);
63
70
  * });
64
71
  * ```
65
72
  */
66
73
  const getUserRedemptions = useCallback(async (
74
+ filters?: { redemptionId?: string; status?: ProcessRecordStatus },
67
75
  options?: PaginationOptions,
68
76
  include?: RedemptionRedeemIncludeRelation[]
69
77
  ): Promise<PaginatedResponseDTO<RedemptionRedeemDTO>> => {
@@ -76,7 +84,7 @@ export const useRedemptions = () => {
76
84
  }
77
85
 
78
86
  try {
79
- const result = await sdk.redemptions.getUserRedemptions(options, include);
87
+ const result = await sdk.redemptions.getUserRedemptions(filters, options, include);
80
88
  return result;
81
89
  } catch (error) {
82
90
  console.error('Failed to fetch user redemptions:', error);
@@ -84,7 +92,57 @@ export const useRedemptions = () => {
84
92
  }
85
93
  }, [sdk, isInitialized, isAuthenticated]);
86
94
 
87
- const redeem = useCallback(async (redemptionId: string, onStatusUpdate?: OnStatusUpdateFn): Promise<RedemptionRedeemRequestResponseDTO> => {
95
+ /**
96
+ * Redeem a redemption offer with optional dynamic context
97
+ *
98
+ * Supports dynamic context for personalized NFT generation when the redemption
99
+ * issues ERC721 tokens. Context can include validity dates, AI prompt placeholders,
100
+ * and custom metadata.
101
+ *
102
+ * @param redemptionId - ID of the redemption to redeem
103
+ * @param options - Optional settings
104
+ * @param options.context - Dynamic context for NFT personalization (validity dates, AI prompts)
105
+ * @param options.onStatusUpdate - Callback for transaction signing status updates
106
+ * @returns Promise resolving to redemption result
107
+ *
108
+ * @example Basic redemption
109
+ * ```typescript
110
+ * const result = await redeem('redemption-123');
111
+ * ```
112
+ *
113
+ * @example Redemption with dynamic context (personalized NFT)
114
+ * ```typescript
115
+ * const result = await redeem('event-ticket-123', {
116
+ * context: {
117
+ * // Validity - token valid for event duration
118
+ * validityDate: new Date().toISOString(),
119
+ * validityDuration: 8, // 8 hours
120
+ *
121
+ * // AI prompt context - available as {{context.xxx}} in prompts
122
+ * attendeeName: 'John Doe',
123
+ * ticketTier: 'VIP',
124
+ * seatSection: 'A12',
125
+ * }
126
+ * });
127
+ * ```
128
+ *
129
+ * @example Hotel stay NFT with check-in/check-out dates
130
+ * ```typescript
131
+ * const result = await redeem('hotel-nft-456', {
132
+ * context: {
133
+ * validityDate: '2026-04-15T14:00:00Z', // Check-in
134
+ * validityEndDate: '2026-04-20T11:00:00Z', // Check-out
135
+ * guestName: 'Jane Smith',
136
+ * roomNumber: '305',
137
+ * roomType: 'Suite',
138
+ * }
139
+ * });
140
+ * ```
141
+ */
142
+ const redeem = useCallback(async (
143
+ redemptionId: string,
144
+ options?: { context?: DynamicContext; onStatusUpdate?: OnStatusUpdateFn }
145
+ ): Promise<RedemptionRedeemRequestResponseDTO> => {
88
146
  if (!isInitialized || !sdk) {
89
147
  throw new Error('SDK not initialized. Call initialize() first.');
90
148
  }
@@ -93,12 +151,12 @@ export const useRedemptions = () => {
93
151
  }
94
152
 
95
153
  try {
96
- const result = await sdk.redemptions.redeem(redemptionId);
154
+ const result = await sdk.redemptions.redeem(redemptionId, options?.context);
97
155
 
98
156
  const txToken = result.senderTransaction?.actionable?.authToken;
99
157
  if (txToken && isSignerAvailable) {
100
158
  try {
101
- const signingResult: SubmissionResult = await signAndSubmitTransactionWithJWT(txToken, onStatusUpdate);
159
+ const signingResult: SubmissionResult = await signAndSubmitTransactionWithJWT(txToken, options?.onStatusUpdate);
102
160
  if (signingResult.success) {
103
161
  // Return enhanced result with signing information
104
162
  return {
@@ -95,10 +95,17 @@ export interface UseTokenBalancesResult {
95
95
  * **Basic Usage:**
96
96
  * ```typescript
97
97
  * import { useTokenBalances, useTokens, usePersSDK } from '@explorins/pers-sdk-react-native';
98
+ * import { useState, useEffect } from 'react';
98
99
  *
99
100
  * function TokenBalancesScreen() {
100
101
  * const { user } = usePersSDK();
101
- * const { availableTokens } = useTokens();
102
+ * const { getTokens } = useTokens();
103
+ * const [availableTokens, setAvailableTokens] = useState([]);
104
+ *
105
+ * // Load tokens on mount
106
+ * useEffect(() => {
107
+ * getTokens().then(result => setAvailableTokens(result.data));
108
+ * }, []);
102
109
  *
103
110
  * // App explicitly selects which wallet to use
104
111
  * const walletAddress = user?.wallets?.[0]?.address;
package/src/index.ts CHANGED
@@ -284,7 +284,7 @@ export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } fr
284
284
  export type { TokenBalanceWithToken, UseTokenBalancesOptions, UseTokenBalancesResult } from './hooks';
285
285
 
286
286
  // Re-export campaign types for convenience
287
- export type { CampaignClaimFilters, CampaignHook } from './hooks';
287
+ export type { CampaignClaimFilters, CampaignHook, GetCampaignsOptions } from './hooks';
288
288
 
289
289
  // Re-export redemption types for convenience
290
290
  export type { RedemptionRedeemFilters, RedemptionHook } from './hooks';