@explorins/pers-sdk-react-native 2.1.2 → 2.1.5
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 +7 -7
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/useAnalytics.d.ts +37 -14
- package/dist/hooks/useAnalytics.d.ts.map +1 -1
- package/dist/hooks/useAnalytics.js +239 -19
- package/dist/hooks/useCampaigns.d.ts +14 -6
- package/dist/hooks/useCampaigns.d.ts.map +1 -1
- package/dist/hooks/useCampaigns.js +144 -10
- package/dist/hooks/useRedemptions.d.ts +5 -2
- package/dist/hooks/useRedemptions.d.ts.map +1 -1
- package/dist/hooks/useRedemptions.js +53 -2
- package/dist/hooks/useTokenBalances.d.ts.map +1 -1
- package/dist/hooks/useTokenBalances.js +21 -8
- package/dist/hooks/useTransactions.d.ts +8 -5
- package/dist/hooks/useTransactions.d.ts.map +1 -1
- package/dist/hooks/useTransactions.js +70 -27
- package/dist/hooks/useTriggerSources.d.ts +76 -0
- package/dist/hooks/useTriggerSources.d.ts.map +1 -0
- package/dist/hooks/useTriggerSources.js +272 -0
- package/dist/index.d.ts +12 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2742 -495
- package/dist/index.js.map +1 -1
- package/dist/providers/PersSDKProvider.d.ts +1 -12
- package/dist/providers/PersSDKProvider.d.ts.map +1 -1
- package/dist/providers/PersSDKProvider.js +50 -25
- package/package.json +2 -2
- package/src/hooks/index.ts +17 -1
- package/src/hooks/useAnalytics.ts +268 -21
- package/src/hooks/useCampaigns.ts +176 -14
- package/src/hooks/useRedemptions.ts +66 -3
- package/src/hooks/useTokenBalances.ts +23 -9
- package/src/hooks/useTransactions.ts +84 -29
- package/src/hooks/useTriggerSources.ts +301 -0
- package/src/index.ts +33 -3
- package/src/providers/PersSDKProvider.tsx +58 -39
|
@@ -5,11 +5,14 @@ import type {
|
|
|
5
5
|
CampaignDTO,
|
|
6
6
|
CampaignClaimDTO,
|
|
7
7
|
CampaignTriggerDTO,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
PaginatedResponseDTO
|
|
8
|
+
PaginatedResponseDTO,
|
|
9
|
+
CampaignClaimIncludeRelation,
|
|
10
|
+
CampaignIncludeRelation
|
|
12
11
|
} from '@explorins/pers-shared';
|
|
12
|
+
import type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
|
|
13
|
+
|
|
14
|
+
// Re-export for consumers
|
|
15
|
+
export type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
|
|
13
16
|
|
|
14
17
|
export const useCampaigns = () => {
|
|
15
18
|
const { sdk, isInitialized, isAuthenticated } = usePersSDK();
|
|
@@ -28,13 +31,30 @@ export const useCampaigns = () => {
|
|
|
28
31
|
}
|
|
29
32
|
}, [sdk, isInitialized]);
|
|
30
33
|
|
|
31
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Get campaign by ID with optional include relations
|
|
36
|
+
*
|
|
37
|
+
* @param campaignId - The campaign ID
|
|
38
|
+
* @param include - Relations to include: 'triggerSources', 'businesses'
|
|
39
|
+
* @returns Promise resolving to campaign data
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // Get campaign with all related data
|
|
44
|
+
* const campaign = await getCampaignById('campaign-123', ['triggerSources', 'businesses']);
|
|
45
|
+
* console.log('Trigger sources:', campaign.included?.triggerSources);
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
const getCampaignById = useCallback(async (
|
|
49
|
+
campaignId: string,
|
|
50
|
+
include?: CampaignIncludeRelation[]
|
|
51
|
+
): Promise<CampaignDTO | null> => {
|
|
32
52
|
if (!isInitialized || !sdk) {
|
|
33
53
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
34
54
|
}
|
|
35
55
|
|
|
36
56
|
try {
|
|
37
|
-
const result = await sdk.campaigns.getCampaignById(campaignId);
|
|
57
|
+
const result = await sdk.campaigns.getCampaignById(campaignId, include);
|
|
38
58
|
return result;
|
|
39
59
|
} catch (error) {
|
|
40
60
|
console.error('Failed to fetch campaign:', error);
|
|
@@ -59,7 +79,29 @@ export const useCampaigns = () => {
|
|
|
59
79
|
}
|
|
60
80
|
}, [sdk, isInitialized, isAuthenticated]);
|
|
61
81
|
|
|
62
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Get user's campaign claims with optional pagination and include relations
|
|
84
|
+
*
|
|
85
|
+
* @param options - Optional options including pagination and include relations
|
|
86
|
+
* @returns Promise resolving to paginated campaign claims
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* // Get user's claims with campaign details
|
|
91
|
+
* const { data: claims } = await getUserClaims({ include: ['campaign', 'business'] });
|
|
92
|
+
* claims.forEach(claim => {
|
|
93
|
+
* console.log('Campaign:', claim.included?.campaign?.title);
|
|
94
|
+
* });
|
|
95
|
+
*
|
|
96
|
+
* // With pagination
|
|
97
|
+
* const { data } = await getUserClaims({ page: 1, limit: 10, include: ['campaign'] });
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
const getUserClaims = useCallback(async (options?: {
|
|
101
|
+
page?: number;
|
|
102
|
+
limit?: number;
|
|
103
|
+
include?: CampaignClaimIncludeRelation[];
|
|
104
|
+
}): Promise<PaginatedResponseDTO<CampaignClaimDTO>> => {
|
|
63
105
|
if (!isInitialized || !sdk) {
|
|
64
106
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
65
107
|
}
|
|
@@ -69,7 +111,7 @@ export const useCampaigns = () => {
|
|
|
69
111
|
}
|
|
70
112
|
|
|
71
113
|
try {
|
|
72
|
-
const result = await sdk.campaigns.getUserClaims();
|
|
114
|
+
const result = await sdk.campaigns.getUserClaims(options);
|
|
73
115
|
return result;
|
|
74
116
|
} catch (error) {
|
|
75
117
|
console.error('Failed to fetch user claims:', error);
|
|
@@ -106,13 +148,32 @@ export const useCampaigns = () => {
|
|
|
106
148
|
}
|
|
107
149
|
}, [sdk, isInitialized]);
|
|
108
150
|
|
|
109
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Admin: Get campaign claims with optional filters and include relations
|
|
153
|
+
*
|
|
154
|
+
* @param filters - Optional filters for campaign, user, or business
|
|
155
|
+
* @param include - Relations to include: 'campaign', 'user', 'business'
|
|
156
|
+
* @returns Promise resolving to paginated campaign claims
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* // Get all claims with user details
|
|
161
|
+
* const { data: claims } = await getCampaignClaims({}, ['user']);
|
|
162
|
+
*
|
|
163
|
+
* // Get claims for a specific campaign
|
|
164
|
+
* const { data } = await getCampaignClaims({ campaignId: 'campaign-123' }, ['user', 'business']);
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
const getCampaignClaims = useCallback(async (
|
|
168
|
+
filters?: CampaignClaimFilters,
|
|
169
|
+
include?: CampaignClaimIncludeRelation[]
|
|
170
|
+
): Promise<PaginatedResponseDTO<CampaignClaimDTO>> => {
|
|
110
171
|
if (!isInitialized || !sdk) {
|
|
111
172
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
112
173
|
}
|
|
113
174
|
|
|
114
175
|
try {
|
|
115
|
-
const result = await sdk.campaigns.getCampaignClaims();
|
|
176
|
+
const result = await sdk.campaigns.getCampaignClaims(filters, include);
|
|
116
177
|
return result;
|
|
117
178
|
} catch (error) {
|
|
118
179
|
console.error('Failed to fetch campaign claims:', error);
|
|
@@ -120,13 +181,23 @@ export const useCampaigns = () => {
|
|
|
120
181
|
}
|
|
121
182
|
}, [sdk, isInitialized]);
|
|
122
183
|
|
|
123
|
-
|
|
184
|
+
/**
|
|
185
|
+
* Admin: Get campaign claims by user ID with optional include relations
|
|
186
|
+
*
|
|
187
|
+
* @param userId - The user ID
|
|
188
|
+
* @param include - Relations to include: 'campaign', 'user', 'business'
|
|
189
|
+
* @returns Promise resolving to paginated campaign claims
|
|
190
|
+
*/
|
|
191
|
+
const getCampaignClaimsByUserId = useCallback(async (
|
|
192
|
+
userId: string,
|
|
193
|
+
include?: CampaignClaimIncludeRelation[]
|
|
194
|
+
): Promise<PaginatedResponseDTO<CampaignClaimDTO>> => {
|
|
124
195
|
if (!isInitialized || !sdk) {
|
|
125
196
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
126
197
|
}
|
|
127
198
|
|
|
128
199
|
try {
|
|
129
|
-
const result = await sdk.campaigns.getCampaignClaimsByUserId(userId);
|
|
200
|
+
const result = await sdk.campaigns.getCampaignClaimsByUserId(userId, undefined, include);
|
|
130
201
|
return result;
|
|
131
202
|
} catch (error) {
|
|
132
203
|
console.error('Failed to fetch campaign claims by user ID:', error);
|
|
@@ -134,13 +205,23 @@ export const useCampaigns = () => {
|
|
|
134
205
|
}
|
|
135
206
|
}, [sdk, isInitialized]);
|
|
136
207
|
|
|
137
|
-
|
|
208
|
+
/**
|
|
209
|
+
* Admin: Get campaign claims by business ID with optional include relations
|
|
210
|
+
*
|
|
211
|
+
* @param businessId - The business ID
|
|
212
|
+
* @param include - Relations to include: 'campaign', 'user', 'business'
|
|
213
|
+
* @returns Promise resolving to paginated campaign claims
|
|
214
|
+
*/
|
|
215
|
+
const getCampaignClaimsByBusinessId = useCallback(async (
|
|
216
|
+
businessId: string,
|
|
217
|
+
include?: CampaignClaimIncludeRelation[]
|
|
218
|
+
): Promise<PaginatedResponseDTO<CampaignClaimDTO>> => {
|
|
138
219
|
if (!isInitialized || !sdk) {
|
|
139
220
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
140
221
|
}
|
|
141
222
|
|
|
142
223
|
try {
|
|
143
|
-
const result = await sdk.campaigns.getCampaignClaimsByBusinessId(businessId);
|
|
224
|
+
const result = await sdk.campaigns.getCampaignClaimsByBusinessId(businessId, undefined, include);
|
|
144
225
|
return result;
|
|
145
226
|
} catch (error) {
|
|
146
227
|
console.error('Failed to fetch campaign claims by business ID:', error);
|
|
@@ -148,6 +229,85 @@ export const useCampaigns = () => {
|
|
|
148
229
|
}
|
|
149
230
|
}, [sdk, isInitialized]);
|
|
150
231
|
|
|
232
|
+
// ==========================================
|
|
233
|
+
// TRIGGER SOURCE ASSIGNMENT (Admin)
|
|
234
|
+
// Note: TriggerSource CRUD is in useTriggerSources hook
|
|
235
|
+
// ==========================================
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Admin: Assign a trigger source to a campaign
|
|
239
|
+
*
|
|
240
|
+
* Associates a trigger source (QR code, NFC tag, etc.) with a campaign.
|
|
241
|
+
* A campaign can have multiple trigger sources.
|
|
242
|
+
*
|
|
243
|
+
* Note: To create/update/delete trigger sources, use `useTriggerSources` hook.
|
|
244
|
+
*
|
|
245
|
+
* @param campaignId - Campaign UUID
|
|
246
|
+
* @param triggerSourceId - Trigger source UUID
|
|
247
|
+
* @returns Promise resolving to updated campaign
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const { create } = useTriggerSources();
|
|
252
|
+
* const { assignTriggerSource } = useCampaigns();
|
|
253
|
+
*
|
|
254
|
+
* // Create trigger source first
|
|
255
|
+
* const source = await create({ type: 'QR_CODE', name: 'Store QR' });
|
|
256
|
+
*
|
|
257
|
+
* // Then assign to campaign
|
|
258
|
+
* const updated = await assignTriggerSource('campaign-123', source.id);
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
const assignTriggerSource = useCallback(async (
|
|
262
|
+
campaignId: string,
|
|
263
|
+
triggerSourceId: string
|
|
264
|
+
): Promise<CampaignDTO> => {
|
|
265
|
+
if (!isInitialized || !sdk) {
|
|
266
|
+
throw new Error('SDK not initialized. Call initialize() first.');
|
|
267
|
+
}
|
|
268
|
+
if (!isAuthenticated) {
|
|
269
|
+
throw new Error('SDK not authenticated. assignTriggerSource requires admin authentication.');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const result = await sdk.campaigns.assignTriggerSource(campaignId, triggerSourceId);
|
|
274
|
+
return result;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error('Failed to assign trigger source:', error);
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
279
|
+
}, [sdk, isInitialized, isAuthenticated]);
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Admin: Remove a trigger source from a campaign
|
|
283
|
+
*
|
|
284
|
+
* Removes the association between a trigger source and a campaign.
|
|
285
|
+
* The trigger source itself is not deleted.
|
|
286
|
+
*
|
|
287
|
+
* @param campaignId - Campaign UUID
|
|
288
|
+
* @param triggerSourceId - Trigger source UUID
|
|
289
|
+
* @returns Promise resolving to updated campaign
|
|
290
|
+
*/
|
|
291
|
+
const removeTriggerSource = useCallback(async (
|
|
292
|
+
campaignId: string,
|
|
293
|
+
triggerSourceId: string
|
|
294
|
+
): Promise<CampaignDTO> => {
|
|
295
|
+
if (!isInitialized || !sdk) {
|
|
296
|
+
throw new Error('SDK not initialized. Call initialize() first.');
|
|
297
|
+
}
|
|
298
|
+
if (!isAuthenticated) {
|
|
299
|
+
throw new Error('SDK not authenticated. removeTriggerSource requires admin authentication.');
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
try {
|
|
303
|
+
const result = await sdk.campaigns.removeTriggerSource(campaignId, triggerSourceId);
|
|
304
|
+
return result;
|
|
305
|
+
} catch (error) {
|
|
306
|
+
console.error('Failed to remove trigger source:', error);
|
|
307
|
+
throw error;
|
|
308
|
+
}
|
|
309
|
+
}, [sdk, isInitialized, isAuthenticated]);
|
|
310
|
+
|
|
151
311
|
return {
|
|
152
312
|
getActiveCampaigns,
|
|
153
313
|
getCampaignById,
|
|
@@ -158,6 +318,8 @@ export const useCampaigns = () => {
|
|
|
158
318
|
getCampaignClaims,
|
|
159
319
|
getCampaignClaimsByUserId,
|
|
160
320
|
getCampaignClaimsByBusinessId,
|
|
321
|
+
assignTriggerSource,
|
|
322
|
+
removeTriggerSource,
|
|
161
323
|
isAvailable: isInitialized && !!sdk?.campaigns,
|
|
162
324
|
};
|
|
163
325
|
};
|
|
@@ -7,8 +7,13 @@ import type {
|
|
|
7
7
|
RedemptionRedeemDTO,
|
|
8
8
|
RedemptionRedeemRequestResponseDTO,
|
|
9
9
|
RedemptionTypeDTO,
|
|
10
|
-
PaginatedResponseDTO
|
|
10
|
+
PaginatedResponseDTO,
|
|
11
|
+
RedemptionRedeemIncludeRelation
|
|
11
12
|
} from '@explorins/pers-shared';
|
|
13
|
+
import type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
|
|
14
|
+
|
|
15
|
+
// Re-export for consumers
|
|
16
|
+
export type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
|
|
12
17
|
|
|
13
18
|
export const useRedemptions = () => {
|
|
14
19
|
const { sdk, isInitialized, isAuthenticated } = usePersSDK();
|
|
@@ -36,7 +41,25 @@ export const useRedemptions = () => {
|
|
|
36
41
|
}
|
|
37
42
|
}, [sdk, isInitialized]);
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Get user's redemption history with optional include relations
|
|
46
|
+
*
|
|
47
|
+
* @param include - Relations to include: 'redemption', 'user', 'business'
|
|
48
|
+
* @returns Promise resolving to paginated redemption history
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* // Get user redemptions with full redemption details
|
|
53
|
+
* const { data: redeems } = await getUserRedemptions(['redemption', 'business']);
|
|
54
|
+
* redeems.forEach(redeem => {
|
|
55
|
+
* console.log('Redemption:', redeem.included?.redemption?.title);
|
|
56
|
+
* console.log('Business:', redeem.included?.business?.displayName);
|
|
57
|
+
* });
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
const getUserRedemptions = useCallback(async (
|
|
61
|
+
include?: RedemptionRedeemIncludeRelation[]
|
|
62
|
+
): Promise<PaginatedResponseDTO<RedemptionRedeemDTO>> => {
|
|
40
63
|
if (!isInitialized || !sdk) {
|
|
41
64
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
42
65
|
}
|
|
@@ -46,7 +69,7 @@ export const useRedemptions = () => {
|
|
|
46
69
|
}
|
|
47
70
|
|
|
48
71
|
try {
|
|
49
|
-
const result = await sdk.redemptions.getUserRedemptions();
|
|
72
|
+
const result = await sdk.redemptions.getUserRedemptions(undefined, include);
|
|
50
73
|
return result;
|
|
51
74
|
} catch (error) {
|
|
52
75
|
console.error('Failed to fetch user redemptions:', error);
|
|
@@ -100,6 +123,45 @@ export const useRedemptions = () => {
|
|
|
100
123
|
}, [sdk, isInitialized, isAuthenticated, signAndSubmitTransactionWithJWT, isSignerAvailable]);
|
|
101
124
|
|
|
102
125
|
// Admin methods
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Admin: Get all redemption redeems with filters and include relations
|
|
129
|
+
*
|
|
130
|
+
* Retrieves all redemption redeems across the platform with filtering.
|
|
131
|
+
*
|
|
132
|
+
* @param filters - Optional filters for user, redemption, and pagination
|
|
133
|
+
* @param include - Relations to include: 'redemption', 'user', 'business'
|
|
134
|
+
* @returns Promise resolving to paginated redemption redeems
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* // Get all redeems with user details
|
|
139
|
+
* const { data: redeems } = await getRedemptionRedeems({}, ['user', 'redemption']);
|
|
140
|
+
*
|
|
141
|
+
* // Filter by specific user
|
|
142
|
+
* const { data: userRedeems } = await getRedemptionRedeems(
|
|
143
|
+
* { userId: 'user-123' },
|
|
144
|
+
* ['redemption']
|
|
145
|
+
* );
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
const getRedemptionRedeems = useCallback(async (
|
|
149
|
+
filters?: RedemptionRedeemFilters,
|
|
150
|
+
include?: RedemptionRedeemIncludeRelation[]
|
|
151
|
+
): Promise<PaginatedResponseDTO<RedemptionRedeemDTO>> => {
|
|
152
|
+
if (!isInitialized || !sdk) {
|
|
153
|
+
throw new Error('SDK not initialized. Call initialize() first.');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const result = await sdk.redemptions.getRedemptionRedeems(filters, include);
|
|
158
|
+
return result;
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error('Failed to fetch redemption redeems:', error);
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}, [sdk, isInitialized]);
|
|
164
|
+
|
|
103
165
|
const createRedemption = useCallback(async (redemptionData: RedemptionCreateRequestDTO): Promise<RedemptionDTO> => {
|
|
104
166
|
if (!isInitialized || !sdk) {
|
|
105
167
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
@@ -161,6 +223,7 @@ export const useRedemptions = () => {
|
|
|
161
223
|
getUserRedemptions,
|
|
162
224
|
redeem,
|
|
163
225
|
getRedemptionTypes,
|
|
226
|
+
getRedemptionRedeems,
|
|
164
227
|
createRedemption,
|
|
165
228
|
updateRedemption,
|
|
166
229
|
toggleRedemptionStatus,
|
|
@@ -151,7 +151,7 @@ export function useTokenBalances(options: UseTokenBalancesOptions): UseTokenBala
|
|
|
151
151
|
refreshInterval = 0
|
|
152
152
|
} = options;
|
|
153
153
|
|
|
154
|
-
const { isAuthenticated } = usePersSDK();
|
|
154
|
+
const { isAuthenticated, sdk } = usePersSDK();
|
|
155
155
|
const web3 = useWeb3();
|
|
156
156
|
|
|
157
157
|
const [tokenBalances, setTokenBalances] = useState<TokenBalanceWithToken[]>([]);
|
|
@@ -268,16 +268,30 @@ export function useTokenBalances(options: UseTokenBalancesOptions): UseTokenBala
|
|
|
268
268
|
}
|
|
269
269
|
}, [autoLoad, isAvailable, availableTokens.length, loadBalances]);
|
|
270
270
|
|
|
271
|
-
//
|
|
271
|
+
// Event-driven refresh: listen for transaction events instead of polling
|
|
272
272
|
useEffect(() => {
|
|
273
|
-
if (refreshInterval
|
|
274
|
-
|
|
273
|
+
if (!sdk || refreshInterval <= 0 || !isAvailable) return;
|
|
274
|
+
|
|
275
|
+
// Subscribe to transaction domain events
|
|
276
|
+
const unsubscribe = sdk.events.subscribe((event) => {
|
|
277
|
+
if (event.domain === 'transaction' && event.type === 'transaction_completed') {
|
|
278
|
+
console.log('[useTokenBalances] Transaction completed, refreshing balances...');
|
|
275
279
|
loadBalances();
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
280
|
+
}
|
|
281
|
+
}, { domains: ['transaction'] });
|
|
282
|
+
|
|
283
|
+
// Also set up a fallback polling interval (much longer than before)
|
|
284
|
+
// This handles cases where events might be missed
|
|
285
|
+
const fallbackInterval = Math.max(refreshInterval, 60000); // Minimum 1 minute
|
|
286
|
+
const intervalId = setInterval(() => {
|
|
287
|
+
loadBalances();
|
|
288
|
+
}, fallbackInterval);
|
|
289
|
+
|
|
290
|
+
return () => {
|
|
291
|
+
unsubscribe();
|
|
292
|
+
clearInterval(intervalId);
|
|
293
|
+
};
|
|
294
|
+
}, [sdk, refreshInterval, isAvailable, loadBalances]);
|
|
281
295
|
|
|
282
296
|
return {
|
|
283
297
|
tokenBalances,
|
|
@@ -5,10 +5,14 @@ import type {
|
|
|
5
5
|
TransactionRequestDTO,
|
|
6
6
|
TransactionRequestResponseDTO,
|
|
7
7
|
TransactionDTO,
|
|
8
|
-
TransactionRole,
|
|
9
8
|
TransactionPaginationRequestDTO,
|
|
10
|
-
PaginatedResponseDTO
|
|
9
|
+
PaginatedResponseDTO,
|
|
10
|
+
TransactionIncludeRelation
|
|
11
11
|
} from '@explorins/pers-shared';
|
|
12
|
+
import type { TransactionQueryOptions } from '@explorins/pers-sdk/transaction';
|
|
13
|
+
|
|
14
|
+
// Re-export for consumers
|
|
15
|
+
export type { TransactionQueryOptions } from '@explorins/pers-sdk/transaction';
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* React hook for transaction operations in the PERS SDK
|
|
@@ -124,26 +128,36 @@ export const useTransactions = () => {
|
|
|
124
128
|
}, [sdk, isInitialized, signAndSubmitTransactionWithJWT, isSignerAvailable]);
|
|
125
129
|
|
|
126
130
|
/**
|
|
127
|
-
* Retrieves a specific transaction by its ID
|
|
131
|
+
* Retrieves a specific transaction by its ID with optional include relations
|
|
128
132
|
*
|
|
129
133
|
* @param transactionId - Unique identifier of the transaction
|
|
134
|
+
* @param include - Optional relations to include (sender, recipient, business) for enriched entity data
|
|
130
135
|
* @returns Promise resolving to transaction data or null if not found
|
|
131
136
|
* @throws Error if SDK is not initialized
|
|
132
137
|
*
|
|
133
138
|
* @example
|
|
134
139
|
* ```typescript
|
|
135
140
|
* const { getTransactionById } = useTransactions();
|
|
141
|
+
*
|
|
142
|
+
* // Basic retrieval
|
|
136
143
|
* const transaction = await getTransactionById('txn-123');
|
|
137
|
-
*
|
|
144
|
+
*
|
|
145
|
+
* // With enriched sender/recipient data
|
|
146
|
+
* const enrichedTx = await getTransactionById('txn-123', ['sender', 'recipient', 'business']);
|
|
147
|
+
* console.log('Sender:', enrichedTx?.included?.sender);
|
|
148
|
+
* console.log('Business:', enrichedTx?.included?.engagedBusiness?.displayName);
|
|
138
149
|
* ```
|
|
139
150
|
*/
|
|
140
|
-
const getTransactionById = useCallback(async (
|
|
151
|
+
const getTransactionById = useCallback(async (
|
|
152
|
+
transactionId: string,
|
|
153
|
+
include?: TransactionIncludeRelation[]
|
|
154
|
+
): Promise<TransactionDTO | null> => {
|
|
141
155
|
if (!isInitialized || !sdk) {
|
|
142
156
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
143
157
|
}
|
|
144
158
|
|
|
145
159
|
try {
|
|
146
|
-
const result = await sdk.transactions.getTransactionById(transactionId);
|
|
160
|
+
const result = await sdk.transactions.getTransactionById(transactionId, include);
|
|
147
161
|
return result;
|
|
148
162
|
} catch (error) {
|
|
149
163
|
console.error('Failed to fetch transaction:', error);
|
|
@@ -152,27 +166,52 @@ export const useTransactions = () => {
|
|
|
152
166
|
}, [sdk, isInitialized]);
|
|
153
167
|
|
|
154
168
|
/**
|
|
155
|
-
* Retrieves transaction history for the authenticated user
|
|
169
|
+
* Retrieves transaction history for the authenticated user with comprehensive filtering
|
|
156
170
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
171
|
+
* Supports filtering by role, status, type, business, token, and more.
|
|
172
|
+
* Optionally enrich with related entities (sender, recipient, business).
|
|
173
|
+
*
|
|
174
|
+
* @param options - Query options including filters, pagination, and include relations
|
|
175
|
+
* @returns Promise resolving to paginated array of user's transactions
|
|
159
176
|
* @throws Error if SDK is not initialized
|
|
160
177
|
*
|
|
161
178
|
* @example
|
|
162
179
|
* ```typescript
|
|
163
180
|
* const { getUserTransactionHistory } = useTransactions();
|
|
164
|
-
*
|
|
165
|
-
*
|
|
181
|
+
*
|
|
182
|
+
* // Simple: Get all transactions
|
|
183
|
+
* const allTransactions = await getUserTransactionHistory();
|
|
184
|
+
*
|
|
185
|
+
* // Filter by role (legacy support)
|
|
186
|
+
* const sentTransactions = await getUserTransactionHistory({ role: 'SENDER' });
|
|
187
|
+
*
|
|
188
|
+
* // Advanced filtering with include relations
|
|
189
|
+
* const filtered = await getUserTransactionHistory({
|
|
190
|
+
* role: 'SENDER',
|
|
191
|
+
* status: 'COMPLETED',
|
|
192
|
+
* engagedBusinessId: 'business-123',
|
|
193
|
+
* include: ['recipient', 'business'],
|
|
194
|
+
* page: 1,
|
|
195
|
+
* limit: 20
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* // Access enriched data
|
|
199
|
+
* filtered.data.forEach(tx => {
|
|
200
|
+
* console.log('Recipient:', tx.included?.recipient);
|
|
201
|
+
* console.log('Business:', tx.included?.engagedBusiness?.displayName);
|
|
202
|
+
* });
|
|
166
203
|
* ```
|
|
167
204
|
*/
|
|
168
|
-
const getUserTransactionHistory = useCallback(async (
|
|
205
|
+
const getUserTransactionHistory = useCallback(async (
|
|
206
|
+
options?: TransactionQueryOptions
|
|
207
|
+
): Promise<PaginatedResponseDTO<TransactionDTO>> => {
|
|
169
208
|
|
|
170
209
|
if (!isInitialized || !sdk) {
|
|
171
210
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
172
211
|
}
|
|
173
212
|
|
|
174
213
|
try {
|
|
175
|
-
const result = await sdk.transactions.getUserTransactionHistory(
|
|
214
|
+
const result = await sdk.transactions.getUserTransactionHistory(options);
|
|
176
215
|
return result;
|
|
177
216
|
} catch (error) {
|
|
178
217
|
console.error('Failed to fetch transaction history:', error);
|
|
@@ -180,27 +219,44 @@ export const useTransactions = () => {
|
|
|
180
219
|
}
|
|
181
220
|
}, [sdk, isInitialized]);
|
|
182
221
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
222
|
+
/**
|
|
223
|
+
* Admin: Get paginated transactions with optional include relations
|
|
224
|
+
*
|
|
225
|
+
* @param params - Pagination and filtering parameters
|
|
226
|
+
* @param include - Optional relations to include for enriched entity data
|
|
227
|
+
* @returns Promise resolving to paginated transaction results
|
|
228
|
+
* @throws Error if SDK is not initialized
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* ```typescript
|
|
232
|
+
* const { getPaginatedTransactions } = useTransactions();
|
|
233
|
+
*
|
|
234
|
+
* // Basic pagination
|
|
235
|
+
* const result = await getPaginatedTransactions({ page: 1, limit: 50 });
|
|
236
|
+
*
|
|
237
|
+
* // With include relations
|
|
238
|
+
* const enrichedResult = await getPaginatedTransactions(
|
|
239
|
+
* { page: 1, limit: 50, sortBy: 'createdAt', sortOrder: 'DESC' },
|
|
240
|
+
* include: ['sender', 'recipient', 'business']
|
|
241
|
+
* });
|
|
242
|
+
*
|
|
243
|
+
* enrichedResult.data.forEach(tx => {
|
|
244
|
+
* console.log('From:', tx.included?.sender);
|
|
245
|
+
* console.log('To:', tx.included?.recipient);
|
|
246
|
+
* });
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
const getPaginatedTransactions = useCallback(async (
|
|
250
|
+
options: TransactionPaginationRequestDTO & {
|
|
251
|
+
include?: TransactionIncludeRelation[];
|
|
194
252
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const getPaginatedTransactions = useCallback(async (params: TransactionPaginationRequestDTO): Promise<any> => {
|
|
253
|
+
): Promise<PaginatedResponseDTO<TransactionDTO>> => {
|
|
198
254
|
if (!isInitialized || !sdk) {
|
|
199
255
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
200
256
|
}
|
|
201
257
|
|
|
202
258
|
try {
|
|
203
|
-
const result = await sdk.transactions.getPaginatedTransactions(
|
|
259
|
+
const result = await sdk.transactions.getPaginatedTransactions(options);
|
|
204
260
|
return result;
|
|
205
261
|
} catch (error) {
|
|
206
262
|
console.error('Failed to fetch paginated transactions:', error);
|
|
@@ -226,7 +282,6 @@ export const useTransactions = () => {
|
|
|
226
282
|
createTransaction,
|
|
227
283
|
getTransactionById,
|
|
228
284
|
getUserTransactionHistory,
|
|
229
|
-
getTenantTransactions,
|
|
230
285
|
getPaginatedTransactions,
|
|
231
286
|
exportTransactionsCSV,
|
|
232
287
|
isAvailable: isInitialized && !!sdk?.transactions,
|