@explorins/pers-sdk-react-native 2.1.13 → 2.1.17
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 +108 -14
- package/dist/hooks/index.d.ts +3 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useAnalytics.d.ts +1 -1
- package/dist/hooks/useAnalytics.d.ts.map +1 -1
- package/dist/hooks/useAuth.d.ts +3 -3
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +5 -17
- package/dist/hooks/useBusiness.d.ts +3 -2
- package/dist/hooks/useBusiness.d.ts.map +1 -1
- package/dist/hooks/useBusiness.js +28 -2
- package/dist/hooks/useCampaigns.d.ts +12 -4
- package/dist/hooks/useCampaigns.d.ts.map +1 -1
- package/dist/hooks/useCampaigns.js +36 -8
- package/dist/hooks/useDonations.d.ts +1 -1
- package/dist/hooks/useDonations.d.ts.map +1 -1
- package/dist/hooks/usePurchases.d.ts +2 -2
- package/dist/hooks/usePurchases.d.ts.map +1 -1
- package/dist/hooks/useRedemptions.d.ts +28 -5
- package/dist/hooks/useRedemptions.d.ts.map +1 -1
- package/dist/hooks/useRedemptions.js +58 -1
- package/dist/hooks/useTenants.d.ts +1 -1
- package/dist/hooks/useTenants.d.ts.map +1 -1
- package/dist/hooks/useTokenBalances.d.ts +1 -1
- package/dist/hooks/useTokenBalances.d.ts.map +1 -1
- package/dist/hooks/useTokenBalances.js +1 -1
- package/dist/hooks/useTokens.d.ts +1 -1
- package/dist/hooks/useTokens.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.d.ts.map +1 -1
- package/dist/hooks/useTransactionSigner.js +38 -11
- package/dist/hooks/useTransactions.d.ts +1 -1
- package/dist/hooks/useTransactions.d.ts.map +1 -1
- package/dist/hooks/useTriggerSources.d.ts +1 -1
- package/dist/hooks/useTriggerSources.d.ts.map +1 -1
- package/dist/hooks/useUserStatus.d.ts +1 -1
- package/dist/hooks/useUserStatus.d.ts.map +1 -1
- package/dist/hooks/useUsers.d.ts +1 -1
- package/dist/hooks/useUsers.d.ts.map +1 -1
- package/dist/index-CzLxqePZ.js +7717 -0
- package/dist/index-CzLxqePZ.js.map +1 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1896 -317
- package/dist/index.js.map +1 -1
- package/dist/providers/PersSDKProvider.d.ts.map +1 -1
- package/dist/providers/PersSDKProvider.js +7 -17
- package/dist/providers/rn-dpop-provider.d.ts.map +1 -1
- package/dist/providers/rn-dpop-provider.js +48 -12
- package/package.json +3 -3
- package/src/hooks/index.ts +5 -2
- package/src/hooks/useAnalytics.ts +1 -1
- package/src/hooks/useAuth.ts +6 -20
- package/src/hooks/useBusiness.ts +32 -3
- package/src/hooks/useCampaigns.ts +49 -12
- package/src/hooks/useDonations.ts +1 -1
- package/src/hooks/usePurchases.ts +1 -1
- package/src/hooks/useRedemptions.ts +91 -6
- package/src/hooks/useTenants.ts +1 -1
- package/src/hooks/useTokenBalances.ts +1 -1
- package/src/hooks/useTokens.ts +1 -1
- package/src/hooks/useTransactionSigner.ts +41 -10
- package/src/hooks/useTransactions.ts +1 -1
- package/src/hooks/useTriggerSources.ts +1 -1
- package/src/hooks/useUserStatus.ts +1 -1
- package/src/hooks/useUsers.ts +1 -1
- package/src/index.ts +6 -3
- package/src/providers/PersSDKProvider.tsx +8 -17
- package/src/providers/rn-dpop-provider.ts +57 -11
|
@@ -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,
|
|
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,CA+NA,CAAC;AAGF,eAAO,MAAM,UAAU,QAAO,cAQ7B,CAAC"}
|
|
@@ -158,22 +158,12 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
158
158
|
if (!sdk)
|
|
159
159
|
return;
|
|
160
160
|
const unsubscribe = sdk.events.subscribe((event) => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const userId = event.details?.userId;
|
|
168
|
-
if (userId) {
|
|
169
|
-
// User ID available, fetch user data
|
|
170
|
-
sdk.users.getCurrentUser()
|
|
171
|
-
.then(userData => {
|
|
172
|
-
setAuthenticationState(userData, true);
|
|
173
|
-
})
|
|
174
|
-
.catch(error => {
|
|
175
|
-
console.error('[PersSDK] Failed to sync restored session:', error);
|
|
176
|
-
});
|
|
161
|
+
// Handle both session restoration and fresh login
|
|
162
|
+
if (event.type === 'session_restored' || event.type === 'login_success') {
|
|
163
|
+
const details = event.details;
|
|
164
|
+
if (details?.user) {
|
|
165
|
+
console.log(`[PersSDK] ${event.type}: syncing user state`);
|
|
166
|
+
setAuthenticationState(details.user, true);
|
|
177
167
|
}
|
|
178
168
|
}
|
|
179
169
|
// Session restoration failed or auth error - clear React state
|
|
@@ -181,7 +171,7 @@ export const PersSDKProvider = ({ children, config }) => {
|
|
|
181
171
|
console.log('[PersSDK] Authentication failed - clearing session');
|
|
182
172
|
setAuthenticationState(null, false);
|
|
183
173
|
}
|
|
184
|
-
}, { domains: ['authentication'] });
|
|
174
|
+
}, { domains: ['authentication'], replay: true });
|
|
185
175
|
return () => {
|
|
186
176
|
unsubscribe();
|
|
187
177
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rn-dpop-provider.d.ts","sourceRoot":"","sources":["../../src/providers/rn-dpop-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"rn-dpop-provider.d.ts","sourceRoot":"","sources":["../../src/providers/rn-dpop-provider.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAgD3E,qBAAa,uBAAwB,YAAW,kBAAkB;IAChE;;;;;OAKG;IACG,eAAe,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,CAAC;IA0C1E,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IA0D9E,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3D,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,eAAe;CAOxB"}
|
|
@@ -1,20 +1,44 @@
|
|
|
1
1
|
import { Platform } from 'react-native';
|
|
2
2
|
import { Buffer } from 'buffer';
|
|
3
|
-
//
|
|
4
|
-
let
|
|
5
|
-
|
|
3
|
+
// Lazy-loaded crypto module - initialized on first use to avoid native module timing issues
|
|
4
|
+
let _crypto = null;
|
|
5
|
+
let _cryptoInitialized = false;
|
|
6
|
+
/**
|
|
7
|
+
* Lazily load the crypto module.
|
|
8
|
+
*
|
|
9
|
+
* Supports customer pre-initialization via global.__QuickCrypto for environments
|
|
10
|
+
* where native module timing is unpredictable (e.g., certain React Native setups).
|
|
11
|
+
*
|
|
12
|
+
* @returns The crypto module or null if unavailable
|
|
13
|
+
*/
|
|
14
|
+
function getCrypto() {
|
|
15
|
+
if (_cryptoInitialized) {
|
|
16
|
+
return _crypto;
|
|
17
|
+
}
|
|
18
|
+
_cryptoInitialized = true;
|
|
19
|
+
if (Platform.OS === 'web') {
|
|
20
|
+
// On Web, we shouldn't be using this provider (Core SDK has WebDPoPProvider)
|
|
21
|
+
_crypto = {
|
|
22
|
+
generateKeyPair: () => { throw new Error('ReactNativeDPoPProvider not supported on Web'); },
|
|
23
|
+
randomUUID: () => globalThis.crypto?.randomUUID?.() || `${Date.now()}-${Math.random()}`
|
|
24
|
+
};
|
|
25
|
+
return _crypto;
|
|
26
|
+
}
|
|
27
|
+
// Check for customer pre-initialized global (for native module timing issues)
|
|
28
|
+
if (typeof global !== 'undefined' && global.__QuickCrypto) {
|
|
29
|
+
_crypto = global.__QuickCrypto;
|
|
30
|
+
return _crypto;
|
|
31
|
+
}
|
|
32
|
+
// Standard lazy load
|
|
6
33
|
try {
|
|
7
|
-
|
|
34
|
+
_crypto = require('react-native-quick-crypto').default || require('react-native-quick-crypto');
|
|
8
35
|
}
|
|
9
36
|
catch (e) {
|
|
10
|
-
console.warn('ReactNativeDPoPProvider: Failed to load react-native-quick-crypto', e);
|
|
37
|
+
console.warn('ReactNativeDPoPProvider: Failed to load react-native-quick-crypto.', e);
|
|
38
|
+
console.warn('Tip: If you encounter timing issues, pre-initialize in index.js: global.__QuickCrypto = require("react-native-quick-crypto")');
|
|
39
|
+
_crypto = null;
|
|
11
40
|
}
|
|
12
|
-
|
|
13
|
-
else {
|
|
14
|
-
// on Web, we shouldn't be using this provider anyway (Core SDK has WebDPoPProvider)
|
|
15
|
-
crypto = {
|
|
16
|
-
generateKeyPair: () => { throw new Error('ReactNativeDPoPProvider not supported on Web'); }
|
|
17
|
-
};
|
|
41
|
+
return _crypto;
|
|
18
42
|
}
|
|
19
43
|
export class ReactNativeDPoPProvider {
|
|
20
44
|
/**
|
|
@@ -24,6 +48,10 @@ export class ReactNativeDPoPProvider {
|
|
|
24
48
|
* Falls back to Node.js crypto API on iOS if needed.
|
|
25
49
|
*/
|
|
26
50
|
async generateKeyPair(options) {
|
|
51
|
+
const crypto = getCrypto();
|
|
52
|
+
if (!crypto) {
|
|
53
|
+
throw new Error('Crypto module not available. Install react-native-quick-crypto or pre-initialize global.__QuickCrypto');
|
|
54
|
+
}
|
|
27
55
|
// Try WebCrypto API first (works on both iOS and Android)
|
|
28
56
|
if (crypto.subtle) {
|
|
29
57
|
try {
|
|
@@ -57,6 +85,10 @@ export class ReactNativeDPoPProvider {
|
|
|
57
85
|
});
|
|
58
86
|
}
|
|
59
87
|
async signProof(payload, keyPair) {
|
|
88
|
+
const crypto = getCrypto();
|
|
89
|
+
if (!crypto) {
|
|
90
|
+
throw new Error('Crypto module not available for signing');
|
|
91
|
+
}
|
|
60
92
|
// 1. Construct Header
|
|
61
93
|
const header = {
|
|
62
94
|
typ: 'dpop+jwt',
|
|
@@ -67,7 +99,7 @@ export class ReactNativeDPoPProvider {
|
|
|
67
99
|
const finalPayload = {
|
|
68
100
|
...payload,
|
|
69
101
|
iat: payload.iat || Math.floor(Date.now() / 1000),
|
|
70
|
-
jti: payload.jti || crypto.randomUUID()
|
|
102
|
+
jti: payload.jti || (crypto.randomUUID?.() || `${Date.now()}-${Math.random()}`)
|
|
71
103
|
};
|
|
72
104
|
// 3. Encode
|
|
73
105
|
const b64Header = this.base64Url(JSON.stringify(header));
|
|
@@ -93,6 +125,10 @@ export class ReactNativeDPoPProvider {
|
|
|
93
125
|
return `${signingInput}.${this.base64UrlBuffer(signature)}`;
|
|
94
126
|
}
|
|
95
127
|
async hashAccessToken(accessToken) {
|
|
128
|
+
const crypto = getCrypto();
|
|
129
|
+
if (!crypto) {
|
|
130
|
+
throw new Error('Crypto module not available for hashing');
|
|
131
|
+
}
|
|
96
132
|
// Try WebCrypto first
|
|
97
133
|
if (crypto.subtle) {
|
|
98
134
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@explorins/pers-sdk-react-native",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.17",
|
|
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.
|
|
40
|
+
"@explorins/pers-sdk": "^2.1.24",
|
|
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.
|
|
158
|
+
"@explorins/pers-shared": "^2.1.128",
|
|
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",
|
package/src/hooks/index.ts
CHANGED
|
@@ -38,10 +38,13 @@ export type {
|
|
|
38
38
|
} from './useTokenBalances';
|
|
39
39
|
|
|
40
40
|
// Export campaign-related types
|
|
41
|
-
export type { CampaignClaimFilters, CampaignHook, GetCampaignsOptions } from './useCampaigns';
|
|
41
|
+
export type { CampaignClaimFilters, CampaignFilterOptions, CampaignHook, GetCampaignsOptions } from './useCampaigns';
|
|
42
42
|
|
|
43
43
|
// Export redemption-related types
|
|
44
|
-
export type { RedemptionRedeemFilters, RedemptionHook } from './useRedemptions';
|
|
44
|
+
export type { RedemptionRedeemFilters, RedemptionFilterOptions, RedemptionHook, GetRedemptionsOptions } from './useRedemptions';
|
|
45
|
+
|
|
46
|
+
// Export business-related types
|
|
47
|
+
export type { BusinessFilterOptions, BusinessHook } from './useBusiness';
|
|
45
48
|
|
|
46
49
|
// Export transaction-related types
|
|
47
50
|
export type { TransactionQueryOptions, TransactionHook } from './useTransactions';
|
package/src/hooks/useAuth.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
|
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
3
|
import type { RawUserData } from '@explorins/pers-sdk/core';
|
|
4
4
|
import { AccountOwnerType } from '@explorins/pers-sdk/core';
|
|
5
|
-
import type { UserDTO,
|
|
5
|
+
import type { UserDTO, SessionAuthContextResponseDTO } from '@explorins/pers-sdk';
|
|
6
6
|
|
|
7
7
|
// Re-export RawUserData for convenience
|
|
8
8
|
export type { RawUserData };
|
|
@@ -80,22 +80,15 @@ export const useAuth = () => {
|
|
|
80
80
|
await authProvider.setAccessToken(jwtToken);
|
|
81
81
|
|
|
82
82
|
// Perform login using the manager
|
|
83
|
+
// SDK emits login_success event with user data - PersSDKProvider handles state sync
|
|
83
84
|
const result = await sdk.auth.loginWithToken(jwtToken, userType);
|
|
84
85
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (userData) {
|
|
88
|
-
setAuthenticationState(userData, true);
|
|
89
|
-
|
|
90
|
-
return result;
|
|
91
|
-
} else {
|
|
92
|
-
throw new Error('No user data returned from login');
|
|
93
|
-
}
|
|
86
|
+
return result;
|
|
94
87
|
} catch (error) {
|
|
95
88
|
console.error('Login failed:', error);
|
|
96
89
|
throw error;
|
|
97
90
|
}
|
|
98
|
-
}, [sdk, authProvider
|
|
91
|
+
}, [sdk, authProvider]);
|
|
99
92
|
|
|
100
93
|
/**
|
|
101
94
|
* Logs in a user using raw user data (direct authentication bypass)
|
|
@@ -116,25 +109,18 @@ export const useAuth = () => {
|
|
|
116
109
|
|
|
117
110
|
try {
|
|
118
111
|
// Use the raw data login from the auth manager
|
|
112
|
+
// SDK emits login_success event with user data - PersSDKProvider handles state sync
|
|
119
113
|
const result = await sdk.auth.loginWithRawData(rawUserData);
|
|
120
114
|
|
|
121
115
|
// Set token from result
|
|
122
116
|
if (result.accessToken) {
|
|
123
117
|
await authProvider.setAccessToken(result.accessToken);
|
|
124
118
|
}
|
|
125
|
-
|
|
126
|
-
const userData = result.user;
|
|
127
|
-
|
|
128
|
-
if (userData) {
|
|
129
|
-
setAuthenticationState(userData, true);
|
|
130
|
-
} else {
|
|
131
|
-
throw new Error('No user data returned from raw data login');
|
|
132
|
-
}
|
|
133
119
|
} catch (error) {
|
|
134
120
|
console.error('Raw data login failed:', error);
|
|
135
121
|
throw error;
|
|
136
122
|
}
|
|
137
|
-
}, [sdk, authProvider
|
|
123
|
+
}, [sdk, authProvider]);
|
|
138
124
|
|
|
139
125
|
/**
|
|
140
126
|
* Logs out the current user and clears authentication state
|
package/src/hooks/useBusiness.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { BusinessDTO, BusinessTypeDTO, BusinessUpdateRequestDTO, BusinessToggleActiveRequestDTO, PaginatedResponseDTO } from '@explorins/pers-
|
|
3
|
+
import type { BusinessDTO, BusinessTypeDTO, BusinessUpdateRequestDTO, BusinessToggleActiveRequestDTO, PaginatedResponseDTO, BusinessFilterOptions } from '@explorins/pers-sdk';
|
|
4
|
+
|
|
5
|
+
// Re-export for consumers
|
|
6
|
+
export type { BusinessFilterOptions } from '@explorins/pers-sdk';
|
|
4
7
|
|
|
5
8
|
/**
|
|
6
9
|
* React hook for business operations in the PERS SDK
|
|
@@ -107,13 +110,39 @@ export const useBusiness = () => {
|
|
|
107
110
|
}
|
|
108
111
|
}, [sdk, isInitialized]);
|
|
109
112
|
|
|
110
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Admin: Get all businesses with optional filtering
|
|
115
|
+
*
|
|
116
|
+
* @param options - Filter and pagination options
|
|
117
|
+
* @returns Promise resolving to paginated businesses
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```typescript
|
|
121
|
+
* // Get all businesses
|
|
122
|
+
* const { data } = await getBusinesses();
|
|
123
|
+
*
|
|
124
|
+
* // Filter by tag
|
|
125
|
+
* const tagged = await getBusinesses({ tag: 'restaurant' });
|
|
126
|
+
*
|
|
127
|
+
* // Multiple tags (OR match)
|
|
128
|
+
* const multiTag = await getBusinesses({ tag: ['restaurant', 'cafe'] });
|
|
129
|
+
*
|
|
130
|
+
* // With search and pagination
|
|
131
|
+
* const filtered = await getBusinesses({
|
|
132
|
+
* search: 'coffee',
|
|
133
|
+
* active: true,
|
|
134
|
+
* page: 1,
|
|
135
|
+
* limit: 20
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
const getBusinesses = useCallback(async (options?: BusinessFilterOptions): Promise<PaginatedResponseDTO<BusinessDTO>> => {
|
|
111
140
|
if (!isInitialized || !sdk) {
|
|
112
141
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
113
142
|
}
|
|
114
143
|
|
|
115
144
|
try {
|
|
116
|
-
const result = await sdk.businesses.getBusinesses();
|
|
145
|
+
const result = await sdk.businesses.getBusinesses(options);
|
|
117
146
|
return result;
|
|
118
147
|
} catch (error) {
|
|
119
148
|
console.error('Failed to fetch all businesses:', error);
|
|
@@ -9,21 +9,30 @@ import type {
|
|
|
9
9
|
CampaignClaimIncludeRelation,
|
|
10
10
|
CampaignIncludeRelation,
|
|
11
11
|
SortOrder,
|
|
12
|
+
CampaignFilterOptions,
|
|
12
13
|
// DynamicContext
|
|
13
|
-
} from '@explorins/pers-
|
|
14
|
+
} from '@explorins/pers-sdk';
|
|
14
15
|
import type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
|
|
15
16
|
|
|
16
17
|
// Re-export for consumers
|
|
17
18
|
export type { CampaignClaimFilters } from '@explorins/pers-sdk/campaign';
|
|
19
|
+
export type { CampaignFilterOptions } from '@explorins/pers-sdk';
|
|
18
20
|
|
|
19
21
|
/**
|
|
20
22
|
* Options for fetching campaigns
|
|
23
|
+
* @deprecated Use CampaignFilterOptions from '@explorins/pers-sdk/campaign' instead
|
|
21
24
|
*/
|
|
22
25
|
export interface GetCampaignsOptions {
|
|
23
|
-
/** Filter by tag */
|
|
24
|
-
|
|
26
|
+
/** Filter by tag(s) - single tag or array for OR match */
|
|
27
|
+
tags?: string | string[];
|
|
28
|
+
/** Free text search across name and description (case-insensitive) */
|
|
29
|
+
search?: string;
|
|
25
30
|
/** Filter by business ID */
|
|
26
31
|
businessId?: string;
|
|
32
|
+
/** Filter campaigns starting on or after this date */
|
|
33
|
+
startDate?: Date | string;
|
|
34
|
+
/** Filter campaigns ending on or before this date */
|
|
35
|
+
endDate?: Date | string;
|
|
27
36
|
/** Page number (1-indexed) */
|
|
28
37
|
page?: number;
|
|
29
38
|
/** Items per page */
|
|
@@ -32,7 +41,7 @@ export interface GetCampaignsOptions {
|
|
|
32
41
|
sortBy?: 'name' | 'createdAt' | 'startDate';
|
|
33
42
|
/** Sort order */
|
|
34
43
|
sortOrder?: SortOrder;
|
|
35
|
-
/** Relations to include: 'triggerSources', 'businesses' */
|
|
44
|
+
/** Relations to include: 'triggerSources', 'businesses', 'claimCount' */
|
|
36
45
|
include?: CampaignIncludeRelation[];
|
|
37
46
|
}
|
|
38
47
|
|
|
@@ -57,11 +66,15 @@ export const useCampaigns = () => {
|
|
|
57
66
|
* include: ['triggerSources', 'businesses']
|
|
58
67
|
* });
|
|
59
68
|
*
|
|
60
|
-
* // Filter by
|
|
61
|
-
* const { data } = await getActiveCampaigns({
|
|
69
|
+
* // Filter by date range
|
|
70
|
+
* const { data } = await getActiveCampaigns({
|
|
71
|
+
* startDate: '2026-05-01',
|
|
72
|
+
* endDate: '2026-12-31'
|
|
73
|
+
* });
|
|
62
74
|
*
|
|
63
|
-
* //
|
|
64
|
-
* const { data } = await getActiveCampaigns({
|
|
75
|
+
* // Get campaigns with claim count
|
|
76
|
+
* const { data } = await getActiveCampaigns({ include: ['claimCount'] });
|
|
77
|
+
* data.forEach(c => console.log(`${c.name}: ${c.claimCount} claims`));
|
|
65
78
|
* ```
|
|
66
79
|
*/
|
|
67
80
|
const getActiveCampaigns = useCallback(async (
|
|
@@ -87,7 +100,7 @@ export const useCampaigns = () => {
|
|
|
87
100
|
* Get campaign by ID with optional include relations
|
|
88
101
|
*
|
|
89
102
|
* @param campaignId - The campaign ID
|
|
90
|
-
* @param include - Relations to include: 'triggerSources', 'businesses'
|
|
103
|
+
* @param include - Relations to include: 'triggerSources', 'businesses', 'claimCount'
|
|
91
104
|
* @returns Promise resolving to campaign data
|
|
92
105
|
*
|
|
93
106
|
* @example
|
|
@@ -95,6 +108,10 @@ export const useCampaigns = () => {
|
|
|
95
108
|
* // Get campaign with all related data
|
|
96
109
|
* const campaign = await getCampaignById('campaign-123', ['triggerSources', 'businesses']);
|
|
97
110
|
* console.log('Trigger sources:', campaign.included?.triggerSources);
|
|
111
|
+
*
|
|
112
|
+
* // Get campaign with claim count
|
|
113
|
+
* const campaign = await getCampaignById('campaign-123', ['claimCount']);
|
|
114
|
+
* console.log('Total claims:', campaign.claimCount);
|
|
98
115
|
* ```
|
|
99
116
|
*/
|
|
100
117
|
const getCampaignById = useCallback(async (
|
|
@@ -257,8 +274,13 @@ export const useCampaigns = () => {
|
|
|
257
274
|
* // Get only active campaigns with trigger sources
|
|
258
275
|
* const { data } = await getAllCampaigns({ active: true, include: ['triggerSources'] });
|
|
259
276
|
*
|
|
260
|
-
* //
|
|
261
|
-
* const { data } = await getAllCampaigns({
|
|
277
|
+
* // Filter by date range with claim count
|
|
278
|
+
* const { data } = await getAllCampaigns({
|
|
279
|
+
* startDate: '2026-05-01',
|
|
280
|
+
* endDate: '2026-12-31',
|
|
281
|
+
* include: ['claimCount']
|
|
282
|
+
* });
|
|
283
|
+
* data.forEach(c => console.log(`${c.name}: ${c.claimCount} claims`));
|
|
262
284
|
*
|
|
263
285
|
* // With pagination and sorting
|
|
264
286
|
* const { data } = await getAllCampaigns({
|
|
@@ -288,7 +310,16 @@ export const useCampaigns = () => {
|
|
|
288
310
|
/**
|
|
289
311
|
* Admin: Get campaign claims with optional filters and include relations
|
|
290
312
|
*
|
|
291
|
-
* @param filters - Optional filters for campaign, user,
|
|
313
|
+
* @param filters - Optional filters for campaign, user, business, and date range
|
|
314
|
+
* @param filters.campaignId - Filter by specific campaign ID
|
|
315
|
+
* @param filters.userId - Filter by user ID
|
|
316
|
+
* @param filters.businessId - Filter by business ID
|
|
317
|
+
* @param filters.dateFrom - Filter claims created on or after this date (ISO 8601 format)
|
|
318
|
+
* @param filters.dateTo - Filter claims created on or before this date (ISO 8601 format)
|
|
319
|
+
* @param filters.page - Page number (1-indexed)
|
|
320
|
+
* @param filters.limit - Items per page
|
|
321
|
+
* @param filters.sortBy - Field to sort by
|
|
322
|
+
* @param filters.sortOrder - Sort direction
|
|
292
323
|
* @param include - Relations to include: 'campaign', 'user', 'business'
|
|
293
324
|
* @returns Promise resolving to paginated campaign claims
|
|
294
325
|
*
|
|
@@ -299,6 +330,12 @@ export const useCampaigns = () => {
|
|
|
299
330
|
*
|
|
300
331
|
* // Get claims for a specific campaign
|
|
301
332
|
* const { data } = await getCampaignClaims({ campaignId: 'campaign-123' }, ['user', 'business']);
|
|
333
|
+
*
|
|
334
|
+
* // Filter by date range
|
|
335
|
+
* const { data } = await getCampaignClaims({
|
|
336
|
+
* dateFrom: '2026-01-01',
|
|
337
|
+
* dateTo: '2026-03-31'
|
|
338
|
+
* }, ['campaign']);
|
|
302
339
|
* ```
|
|
303
340
|
*/
|
|
304
341
|
const getCampaignClaims = useCallback(async (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { DonationTypeDTO, PaginatedResponseDTO } from '@explorins/pers-
|
|
3
|
+
import type { DonationTypeDTO, PaginatedResponseDTO } from '@explorins/pers-sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* React hook for donation operations in the PERS SDK
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { PurchaseTokenDTO, PurchaseDTO, PaginatedResponseDTO } from '@explorins/pers-
|
|
3
|
+
import type { PurchaseTokenDTO, PurchaseDTO, PaginatedResponseDTO } from '@explorins/pers-sdk';
|
|
4
4
|
|
|
5
5
|
export const usePurchases = () => {
|
|
6
6
|
const { sdk, isInitialized, isAuthenticated } = usePersSDK();
|
|
@@ -9,14 +9,42 @@ import type {
|
|
|
9
9
|
RedemptionTypeDTO,
|
|
10
10
|
PaginatedResponseDTO,
|
|
11
11
|
RedemptionRedeemIncludeRelation,
|
|
12
|
+
RedemptionIncludeRelation,
|
|
12
13
|
ProcessRecordStatus,
|
|
13
|
-
DynamicContext
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
DynamicContext,
|
|
15
|
+
SortOrder
|
|
16
|
+
} from '@explorins/pers-sdk';
|
|
17
|
+
import type { RedemptionRedeemFilters, RedemptionFilterOptions } from '@explorins/pers-sdk/redemption';
|
|
16
18
|
import type { PaginationOptions } from '@explorins/pers-sdk';
|
|
17
19
|
|
|
18
20
|
// Re-export for consumers
|
|
19
|
-
export type { RedemptionRedeemFilters } from '@explorins/pers-sdk/redemption';
|
|
21
|
+
export type { RedemptionRedeemFilters, RedemptionFilterOptions } from '@explorins/pers-sdk/redemption';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Options for fetching redemptions with filtering and pagination
|
|
25
|
+
*/
|
|
26
|
+
export interface GetRedemptionsOptions {
|
|
27
|
+
/** Filter by active status (Admin only - regular users always see active offers) */
|
|
28
|
+
active?: boolean;
|
|
29
|
+
/** Free text search across name, description, tags (case-insensitive) */
|
|
30
|
+
search?: string;
|
|
31
|
+
/** Filter by tag(s) - single tag or array for OR match */
|
|
32
|
+
tags?: string | string[];
|
|
33
|
+
/** Filter redemptions starting on or after this date */
|
|
34
|
+
startDate?: Date | string;
|
|
35
|
+
/** Filter redemptions ending on or before this date */
|
|
36
|
+
endDate?: Date | string;
|
|
37
|
+
/** Relations to include: 'redeemCount' */
|
|
38
|
+
include?: RedemptionIncludeRelation[];
|
|
39
|
+
/** Page number (1-indexed) */
|
|
40
|
+
page?: number;
|
|
41
|
+
/** Results per page */
|
|
42
|
+
limit?: number;
|
|
43
|
+
/** Field to sort by */
|
|
44
|
+
sortBy?: 'name' | 'createdAt' | 'startDate';
|
|
45
|
+
/** Sort direction */
|
|
46
|
+
sortOrder?: SortOrder;
|
|
47
|
+
}
|
|
20
48
|
|
|
21
49
|
export const useRedemptions = () => {
|
|
22
50
|
const { sdk, isInitialized, isAuthenticated } = usePersSDK();
|
|
@@ -29,8 +57,49 @@ export const useRedemptions = () => {
|
|
|
29
57
|
* **Administrators:** Can see all redemptions and filter by active/inactive status
|
|
30
58
|
*
|
|
31
59
|
* The backend enforces permission-based filtering automatically.
|
|
60
|
+
*
|
|
61
|
+
* @param options - Filter and pagination options
|
|
62
|
+
* @param options.active - Filter by active status (Admin only)
|
|
63
|
+
* @param options.search - Free text search across name, description, tags
|
|
64
|
+
* @param options.startDate - Filter redemptions starting on or after this date
|
|
65
|
+
* @param options.endDate - Filter redemptions ending on or before this date
|
|
66
|
+
* @param options.include - Relations to include: 'redeemCount'
|
|
67
|
+
* @param options.page - Page number (1-indexed)
|
|
68
|
+
* @param options.limit - Results per page
|
|
69
|
+
* @param options.sortBy - Field to sort by ('name' | 'createdAt')
|
|
70
|
+
* @param options.sortOrder - Sort direction ('ASC' | 'DESC')
|
|
71
|
+
*
|
|
72
|
+
* @example Basic usage
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const { data: offers } = await getRedemptions();
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @example Filter by date range
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const { data: dateFiltered } = await getRedemptions({
|
|
80
|
+
* startDate: '2026-05-01',
|
|
81
|
+
* endDate: '2026-06-30'
|
|
82
|
+
* });
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example Get redemptions with redeem count
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const { data: offers } = await getRedemptions({ include: ['redeemCount'] });
|
|
88
|
+
* offers.forEach(o => console.log(`${o.name}: ${o.redeemCount} redeems`));
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @example Search with pagination
|
|
92
|
+
* ```typescript
|
|
93
|
+
* const { data, pagination } = await getRedemptions({
|
|
94
|
+
* search: 'discount',
|
|
95
|
+
* page: 1,
|
|
96
|
+
* limit: 10,
|
|
97
|
+
* sortBy: 'name',
|
|
98
|
+
* sortOrder: 'ASC'
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
32
101
|
*/
|
|
33
|
-
const getRedemptions = useCallback(async (options?:
|
|
102
|
+
const getRedemptions = useCallback(async (options?: GetRedemptionsOptions): Promise<PaginatedResponseDTO<RedemptionDTO>> => {
|
|
34
103
|
if (!isInitialized || !sdk) {
|
|
35
104
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
36
105
|
}
|
|
@@ -194,7 +263,17 @@ export const useRedemptions = () => {
|
|
|
194
263
|
*
|
|
195
264
|
* Retrieves all redemption redeems across the platform with filtering.
|
|
196
265
|
*
|
|
197
|
-
* @param filters - Optional filters for user, redemption, and pagination
|
|
266
|
+
* @param filters - Optional filters for user, redemption, date range, and pagination
|
|
267
|
+
* @param filters.userId - Filter by user ID
|
|
268
|
+
* @param filters.redemptionId - Filter by redemption offer ID
|
|
269
|
+
* @param filters.businessId - Filter by business ID (admin only)
|
|
270
|
+
* @param filters.status - Filter by processing status (PENDING, PROCESSING, COMPLETED, FAILED)
|
|
271
|
+
* @param filters.dateFrom - Filter redeems created on or after this date (ISO 8601 format)
|
|
272
|
+
* @param filters.dateTo - Filter redeems created on or before this date (ISO 8601 format)
|
|
273
|
+
* @param filters.page - Page number (1-indexed)
|
|
274
|
+
* @param filters.limit - Items per page
|
|
275
|
+
* @param filters.sortBy - Field to sort by
|
|
276
|
+
* @param filters.sortOrder - Sort direction
|
|
198
277
|
* @param include - Relations to include: 'redemption', 'user', 'business'
|
|
199
278
|
* @returns Promise resolving to paginated redemption redeems
|
|
200
279
|
*
|
|
@@ -208,6 +287,12 @@ export const useRedemptions = () => {
|
|
|
208
287
|
* { userId: 'user-123' },
|
|
209
288
|
* ['redemption']
|
|
210
289
|
* );
|
|
290
|
+
*
|
|
291
|
+
* // Filter by date range
|
|
292
|
+
* const { data } = await getRedemptionRedeems({
|
|
293
|
+
* dateFrom: '2026-01-01',
|
|
294
|
+
* dateTo: '2026-03-31'
|
|
295
|
+
* }, ['user', 'redemption']);
|
|
211
296
|
* ```
|
|
212
297
|
*/
|
|
213
298
|
const getRedemptionRedeems = useCallback(async (
|
package/src/hooks/useTenants.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { TenantPublicDTO, TenantClientConfigDTO, AdminDTO, PaginatedResponseDTO } from '@explorins/pers-
|
|
3
|
+
import type { TenantPublicDTO, TenantClientConfigDTO, AdminDTO, PaginatedResponseDTO } from '@explorins/pers-sdk';
|
|
4
4
|
|
|
5
5
|
export const useTenants = () => {
|
|
6
6
|
const { sdk, isInitialized } = usePersSDK();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect, useState, useRef } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
3
|
import { useWeb3 } from './useWeb3';
|
|
4
|
-
import { NativeTokenTypes, type TokenDTO } from '@explorins/pers-
|
|
4
|
+
import { NativeTokenTypes, type TokenDTO } from '@explorins/pers-sdk';
|
|
5
5
|
import type { TokenBalance, TokenBalanceRequest } from '@explorins/pers-sdk/web3';
|
|
6
6
|
|
|
7
7
|
/**
|
package/src/hooks/useTokens.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback } from 'react';
|
|
2
2
|
import { usePersSDK } from '../providers/PersSDKProvider';
|
|
3
|
-
import type { TokenDTO, PaginatedResponseDTO } from '@explorins/pers-
|
|
3
|
+
import type { TokenDTO, PaginatedResponseDTO } from '@explorins/pers-sdk';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* React hook for token operations in the PERS SDK
|