@explorins/pers-sdk-react-native 2.1.7 → 2.1.10
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/dist/hooks/useCampaigns.d.ts +24 -3
- package/dist/hooks/useCampaigns.d.ts.map +1 -1
- package/dist/hooks/useCampaigns.js +58 -4
- package/dist/hooks/useTokenBalances.d.ts +6 -13
- package/dist/hooks/useTokenBalances.d.ts.map +1 -1
- package/dist/hooks/useTokenBalances.js +6 -27
- package/dist/index.js +186 -59
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/hooks/useCampaigns.ts +84 -5
- package/src/hooks/useTokenBalances.ts +11 -29
package/dist/index.js
CHANGED
|
@@ -9602,6 +9602,12 @@ class PersApiClient {
|
|
|
9602
9602
|
try {
|
|
9603
9603
|
const refreshSuccessful = await this.refreshManager.attemptInternalRefresh();
|
|
9604
9604
|
if (refreshSuccessful) {
|
|
9605
|
+
// Emit TOKEN_REFRESHED event so WS clients can retry if they gave up
|
|
9606
|
+
this._events?.emitSuccess({
|
|
9607
|
+
type: 'token_refreshed',
|
|
9608
|
+
domain: 'authentication',
|
|
9609
|
+
userMessage: 'Authentication token refreshed',
|
|
9610
|
+
});
|
|
9605
9611
|
return await this.request(method, endpoint, body, { ...options, retryCount: 1 });
|
|
9606
9612
|
}
|
|
9607
9613
|
}
|
|
@@ -9886,7 +9892,7 @@ class PersEventEmitter {
|
|
|
9886
9892
|
* ```typescript
|
|
9887
9893
|
* sdk.events.emitSuccess({
|
|
9888
9894
|
* domain: 'transaction', // Only business domains allowed
|
|
9889
|
-
* type: '
|
|
9895
|
+
* type: 'transaction_confirmed',
|
|
9890
9896
|
* userMessage: 'Transaction confirmed!'
|
|
9891
9897
|
* });
|
|
9892
9898
|
* ```
|
|
@@ -9913,7 +9919,7 @@ class PersEventEmitter {
|
|
|
9913
9919
|
* ```typescript
|
|
9914
9920
|
* sdk.events.emitError({
|
|
9915
9921
|
* domain: 'validation', // Technical domains allowed
|
|
9916
|
-
* type: '
|
|
9922
|
+
* type: 'validation_failed',
|
|
9917
9923
|
* userMessage: 'Please check your input'
|
|
9918
9924
|
* });
|
|
9919
9925
|
* ```
|
|
@@ -10047,7 +10053,7 @@ class AuthManager {
|
|
|
10047
10053
|
: await authService.loginUser(jwtToken);
|
|
10048
10054
|
this.events?.emitSuccess({
|
|
10049
10055
|
domain: 'authentication',
|
|
10050
|
-
type: '
|
|
10056
|
+
type: 'login_success',
|
|
10051
10057
|
userMessage: 'Successfully logged in'
|
|
10052
10058
|
});
|
|
10053
10059
|
return result;
|
|
@@ -10420,7 +10426,7 @@ class UserManager {
|
|
|
10420
10426
|
const result = await this.userService.updateRemoteUser(userData);
|
|
10421
10427
|
this.events?.emitSuccess({
|
|
10422
10428
|
domain: 'user',
|
|
10423
|
-
type: '
|
|
10429
|
+
type: 'profile_updated',
|
|
10424
10430
|
userMessage: 'Profile updated successfully',
|
|
10425
10431
|
details: { userId: result.id }
|
|
10426
10432
|
});
|
|
@@ -10700,7 +10706,7 @@ class UserManager {
|
|
|
10700
10706
|
const result = await this.userService.deleteUser(identifier);
|
|
10701
10707
|
this.events?.emitSuccess({
|
|
10702
10708
|
domain: 'user',
|
|
10703
|
-
type: '
|
|
10709
|
+
type: 'user_deleted',
|
|
10704
10710
|
userMessage: 'User deleted successfully',
|
|
10705
10711
|
details: { identifier }
|
|
10706
10712
|
});
|
|
@@ -10733,7 +10739,7 @@ class UserManager {
|
|
|
10733
10739
|
const result = await this.userService.restoreUser(identifier);
|
|
10734
10740
|
this.events?.emitSuccess({
|
|
10735
10741
|
domain: 'user',
|
|
10736
|
-
type: '
|
|
10742
|
+
type: 'user_restored',
|
|
10737
10743
|
userMessage: 'User restored successfully',
|
|
10738
10744
|
details: { identifier, userId: result.id }
|
|
10739
10745
|
});
|
|
@@ -11423,7 +11429,7 @@ class BusinessManager {
|
|
|
11423
11429
|
const result = await this.businessService.createBusinessByDisplayName(displayName);
|
|
11424
11430
|
this.events?.emitSuccess({
|
|
11425
11431
|
domain: 'business',
|
|
11426
|
-
type: '
|
|
11432
|
+
type: 'business_created',
|
|
11427
11433
|
userMessage: 'Business created successfully',
|
|
11428
11434
|
details: { businessId: result.id, displayName: result.displayName }
|
|
11429
11435
|
});
|
|
@@ -11458,7 +11464,7 @@ class BusinessManager {
|
|
|
11458
11464
|
const result = await this.businessService.updateBusiness(businessId, businessData);
|
|
11459
11465
|
this.events?.emitSuccess({
|
|
11460
11466
|
domain: 'business',
|
|
11461
|
-
type: '
|
|
11467
|
+
type: 'business_updated',
|
|
11462
11468
|
userMessage: 'Business updated successfully',
|
|
11463
11469
|
details: { businessId: result.id, displayName: result.displayName }
|
|
11464
11470
|
});
|
|
@@ -11630,7 +11636,7 @@ class BusinessManager {
|
|
|
11630
11636
|
const result = await this.membershipService.updateMemberRole(businessId, userId, newRole);
|
|
11631
11637
|
this.events?.emitSuccess({
|
|
11632
11638
|
domain: 'business',
|
|
11633
|
-
type: '
|
|
11639
|
+
type: 'membership_updated',
|
|
11634
11640
|
userMessage: 'Membership role updated',
|
|
11635
11641
|
details: { businessId, userId, role: newRole }
|
|
11636
11642
|
});
|
|
@@ -11908,7 +11914,7 @@ class CampaignManager {
|
|
|
11908
11914
|
const result = await this.campaignService.claimCampaign(claimRequest);
|
|
11909
11915
|
this.events?.emitSuccess({
|
|
11910
11916
|
domain: 'campaign',
|
|
11911
|
-
type: '
|
|
11917
|
+
type: 'claim_success',
|
|
11912
11918
|
userMessage: 'Campaign reward claimed successfully',
|
|
11913
11919
|
details: { campaignId: claimRequest.campaignId }
|
|
11914
11920
|
});
|
|
@@ -12176,7 +12182,7 @@ class CampaignManager {
|
|
|
12176
12182
|
const result = await this.campaignService.createCampaignTrigger(data);
|
|
12177
12183
|
this.events?.emitSuccess({
|
|
12178
12184
|
domain: 'campaign',
|
|
12179
|
-
type: '
|
|
12185
|
+
type: 'campaign_trigger_created',
|
|
12180
12186
|
userMessage: `Trigger "${data.name}" created successfully`,
|
|
12181
12187
|
details: { triggerId: result.id, name: data.name }
|
|
12182
12188
|
});
|
|
@@ -12201,7 +12207,7 @@ class CampaignManager {
|
|
|
12201
12207
|
const result = await this.campaignService.updateCampaignTrigger(triggerId, data);
|
|
12202
12208
|
this.events?.emitSuccess({
|
|
12203
12209
|
domain: 'campaign',
|
|
12204
|
-
type: '
|
|
12210
|
+
type: 'campaign_trigger_updated',
|
|
12205
12211
|
userMessage: 'Trigger updated successfully',
|
|
12206
12212
|
details: { triggerId, updates: Object.keys(data) }
|
|
12207
12213
|
});
|
|
@@ -12222,7 +12228,7 @@ class CampaignManager {
|
|
|
12222
12228
|
const result = await this.campaignService.deleteCampaignTrigger(triggerId);
|
|
12223
12229
|
this.events?.emitSuccess({
|
|
12224
12230
|
domain: 'campaign',
|
|
12225
|
-
type: '
|
|
12231
|
+
type: 'campaign_trigger_deleted',
|
|
12226
12232
|
userMessage: 'Trigger deleted successfully',
|
|
12227
12233
|
details: { triggerId }
|
|
12228
12234
|
});
|
|
@@ -12251,7 +12257,7 @@ class CampaignManager {
|
|
|
12251
12257
|
const result = await this.campaignService.setCampaignTrigger(campaignId, triggerId);
|
|
12252
12258
|
this.events?.emitSuccess({
|
|
12253
12259
|
domain: 'campaign',
|
|
12254
|
-
type: '
|
|
12260
|
+
type: 'campaign_trigger_assigned',
|
|
12255
12261
|
userMessage: 'Trigger assigned to campaign',
|
|
12256
12262
|
details: { campaignId, triggerId }
|
|
12257
12263
|
});
|
|
@@ -12280,7 +12286,7 @@ class CampaignManager {
|
|
|
12280
12286
|
const result = await this.campaignService.removeCampaignTrigger(campaignId, triggerId);
|
|
12281
12287
|
this.events?.emitSuccess({
|
|
12282
12288
|
domain: 'campaign',
|
|
12283
|
-
type: '
|
|
12289
|
+
type: 'campaign_trigger_removed',
|
|
12284
12290
|
userMessage: 'Trigger removed from campaign',
|
|
12285
12291
|
details: { campaignId, triggerId }
|
|
12286
12292
|
});
|
|
@@ -12616,7 +12622,7 @@ class CampaignManager {
|
|
|
12616
12622
|
const result = await this.campaignService.assignTriggerSourceToCampaign(campaignId, triggerSourceId);
|
|
12617
12623
|
this.events?.emitSuccess({
|
|
12618
12624
|
domain: 'campaign',
|
|
12619
|
-
type: '
|
|
12625
|
+
type: 'trigger_source_assigned',
|
|
12620
12626
|
userMessage: 'Trigger source assigned to campaign',
|
|
12621
12627
|
details: { campaignId, triggerSourceId }
|
|
12622
12628
|
});
|
|
@@ -12964,7 +12970,7 @@ class RedemptionManager {
|
|
|
12964
12970
|
const result = await this.redemptionService.redeemRedemption(redemptionId);
|
|
12965
12971
|
this.events?.emitSuccess({
|
|
12966
12972
|
domain: 'redemption',
|
|
12967
|
-
type: '
|
|
12973
|
+
type: 'redeem_success',
|
|
12968
12974
|
userMessage: 'Reward redeemed successfully',
|
|
12969
12975
|
details: { redemptionId }
|
|
12970
12976
|
});
|
|
@@ -13482,7 +13488,7 @@ class TransactionManager {
|
|
|
13482
13488
|
const result = await this.transactionService.createTransaction(transactionData);
|
|
13483
13489
|
this.events?.emitSuccess({
|
|
13484
13490
|
domain: 'transaction',
|
|
13485
|
-
type: '
|
|
13491
|
+
type: 'transaction_created',
|
|
13486
13492
|
userMessage: 'Transaction created successfully',
|
|
13487
13493
|
details: { transactionId: result.transaction?.id }
|
|
13488
13494
|
});
|
|
@@ -13721,7 +13727,7 @@ class TransactionManager {
|
|
|
13721
13727
|
const result = await this.transactionService.submitSignedTransaction(signedTxData);
|
|
13722
13728
|
this.events?.emitSuccess({
|
|
13723
13729
|
domain: 'transaction',
|
|
13724
|
-
type: '
|
|
13730
|
+
type: 'transaction_submitted',
|
|
13725
13731
|
userMessage: 'Transaction submitted successfully',
|
|
13726
13732
|
details: { transactionId: result.transaction?.id }
|
|
13727
13733
|
});
|
|
@@ -15645,7 +15651,7 @@ class TriggerSourceManager {
|
|
|
15645
15651
|
const result = await this.triggerSourceService.createTriggerSource(triggerSource);
|
|
15646
15652
|
this.events?.emitSuccess({
|
|
15647
15653
|
domain: 'trigger-source',
|
|
15648
|
-
type: '
|
|
15654
|
+
type: 'trigger_source_created',
|
|
15649
15655
|
userMessage: 'Trigger source created successfully',
|
|
15650
15656
|
details: { triggerSourceId: result.id, type: result.type }
|
|
15651
15657
|
});
|
|
@@ -15677,7 +15683,7 @@ class TriggerSourceManager {
|
|
|
15677
15683
|
const result = await this.triggerSourceService.updateTriggerSource(triggerSourceId, triggerSource);
|
|
15678
15684
|
this.events?.emitSuccess({
|
|
15679
15685
|
domain: 'trigger-source',
|
|
15680
|
-
type: '
|
|
15686
|
+
type: 'trigger_source_updated',
|
|
15681
15687
|
userMessage: 'Trigger source updated successfully',
|
|
15682
15688
|
details: { triggerSourceId }
|
|
15683
15689
|
});
|
|
@@ -15704,7 +15710,7 @@ class TriggerSourceManager {
|
|
|
15704
15710
|
const result = await this.triggerSourceService.deleteTriggerSource(triggerSourceId);
|
|
15705
15711
|
this.events?.emitSuccess({
|
|
15706
15712
|
domain: 'trigger-source',
|
|
15707
|
-
type: '
|
|
15713
|
+
type: 'trigger_source_deleted',
|
|
15708
15714
|
userMessage: 'Trigger source deleted successfully',
|
|
15709
15715
|
details: { triggerSourceId }
|
|
15710
15716
|
});
|
|
@@ -16178,7 +16184,7 @@ class WebhookManager {
|
|
|
16178
16184
|
const result = await this.webhookService.createWebhook(webhook);
|
|
16179
16185
|
this.events?.emitSuccess({
|
|
16180
16186
|
domain: 'webhook',
|
|
16181
|
-
type: '
|
|
16187
|
+
type: 'webhook_created',
|
|
16182
16188
|
userMessage: 'Webhook created successfully',
|
|
16183
16189
|
details: { webhookId: result.id, name: result.name }
|
|
16184
16190
|
});
|
|
@@ -16195,7 +16201,7 @@ class WebhookManager {
|
|
|
16195
16201
|
const result = await this.webhookService.updateWebhook(webhookId, webhook);
|
|
16196
16202
|
this.events?.emitSuccess({
|
|
16197
16203
|
domain: 'webhook',
|
|
16198
|
-
type: '
|
|
16204
|
+
type: 'webhook_updated',
|
|
16199
16205
|
userMessage: 'Webhook updated successfully',
|
|
16200
16206
|
details: { webhookId }
|
|
16201
16207
|
});
|
|
@@ -16223,7 +16229,7 @@ class WebhookManager {
|
|
|
16223
16229
|
const result = await this.webhookService.deleteWebhook(webhookId);
|
|
16224
16230
|
this.events?.emitSuccess({
|
|
16225
16231
|
domain: 'webhook',
|
|
16226
|
-
type: '
|
|
16232
|
+
type: 'webhook_deleted',
|
|
16227
16233
|
userMessage: 'Webhook deleted successfully',
|
|
16228
16234
|
details: { webhookId }
|
|
16229
16235
|
});
|
|
@@ -16280,7 +16286,7 @@ class WebhookManager {
|
|
|
16280
16286
|
const result = await this.webhookService.post(hookId, body);
|
|
16281
16287
|
this.events?.emitSuccess({
|
|
16282
16288
|
domain: 'webhook',
|
|
16283
|
-
type: '
|
|
16289
|
+
type: 'webhook_triggered',
|
|
16284
16290
|
userMessage: 'Webhook triggered',
|
|
16285
16291
|
details: { hookId, executionId: result.executionId }
|
|
16286
16292
|
});
|
|
@@ -16844,12 +16850,22 @@ class WalletEventsManager {
|
|
|
16844
16850
|
this.client = null;
|
|
16845
16851
|
this.pendingHandlers = [];
|
|
16846
16852
|
this.unsubscribes = [];
|
|
16853
|
+
// Track if WS gave up reconnecting (so we can retry on token refresh)
|
|
16854
|
+
this.reconnectGaveUp = false;
|
|
16855
|
+
this.lastSubscriptions = { wallets: [], chains: [] };
|
|
16847
16856
|
this.config = {
|
|
16848
16857
|
autoReconnect: true,
|
|
16849
16858
|
connectionTimeout: 30000,
|
|
16850
16859
|
debug: false,
|
|
16851
16860
|
...config,
|
|
16852
16861
|
};
|
|
16862
|
+
// Subscribe to auth events to retry WS connection when tokens are refreshed
|
|
16863
|
+
this.authEventUnsubscribe = this.eventEmitter.subscribe((event) => {
|
|
16864
|
+
if (event.type === 'token_refreshed' && this.reconnectGaveUp) {
|
|
16865
|
+
// Tokens were refreshed and WS had given up - retry connection
|
|
16866
|
+
this.retryAfterTokenRefresh();
|
|
16867
|
+
}
|
|
16868
|
+
}, { domains: ['authentication'], levels: ['success'] });
|
|
16853
16869
|
}
|
|
16854
16870
|
/**
|
|
16855
16871
|
* Connect to real-time wallet events
|
|
@@ -16878,8 +16894,11 @@ class WalletEventsManager {
|
|
|
16878
16894
|
const wsUrl = this.config.wsUrl
|
|
16879
16895
|
|| sdkConfig.walletEventsWsUrl
|
|
16880
16896
|
|| buildWalletEventsWsUrl(sdkConfig.environment);
|
|
16881
|
-
// Create token refresher that
|
|
16897
|
+
// Create token refresher that ensures valid token before reconnecting
|
|
16898
|
+
// This triggers actual token refresh if expired, not just retrieval
|
|
16882
16899
|
const tokenRefresher = async () => {
|
|
16900
|
+
// Ensure token is refreshed if expired (calls refresh API if needed)
|
|
16901
|
+
await this.apiClient.ensureValidToken();
|
|
16883
16902
|
const freshToken = await authProvider.getToken();
|
|
16884
16903
|
if (!freshToken) {
|
|
16885
16904
|
throw new Error('Failed to refresh token');
|
|
@@ -16894,6 +16913,32 @@ class WalletEventsManager {
|
|
|
16894
16913
|
tokenRefresher,
|
|
16895
16914
|
});
|
|
16896
16915
|
await this.client.connect(token);
|
|
16916
|
+
// Reset gave-up flag on successful connection
|
|
16917
|
+
this.reconnectGaveUp = false;
|
|
16918
|
+
// Track previous state to detect reconnections and give-ups
|
|
16919
|
+
let previousState = 'connected';
|
|
16920
|
+
// Clean up previous state change listener (prevent duplicate listeners)
|
|
16921
|
+
this.stateChangeUnsubscribe?.();
|
|
16922
|
+
// Listen for state changes
|
|
16923
|
+
this.stateChangeUnsubscribe = this.client.onStateChange((state) => {
|
|
16924
|
+
if (state === 'disconnected' && previousState === 'reconnecting') {
|
|
16925
|
+
// Transitioned from reconnecting to disconnected = exhausted all attempts
|
|
16926
|
+
this.reconnectGaveUp = true;
|
|
16927
|
+
}
|
|
16928
|
+
else if (state === 'connected') {
|
|
16929
|
+
this.reconnectGaveUp = false;
|
|
16930
|
+
// Emit reconnected event so apps can refresh state (catch missed events)
|
|
16931
|
+
if (previousState === 'reconnecting') {
|
|
16932
|
+
this.eventEmitter.emitSuccess({
|
|
16933
|
+
type: 'wallet_reconnected',
|
|
16934
|
+
domain: 'wallet',
|
|
16935
|
+
userMessage: 'Wallet events reconnected',
|
|
16936
|
+
details: { previousState }
|
|
16937
|
+
});
|
|
16938
|
+
}
|
|
16939
|
+
}
|
|
16940
|
+
previousState = state;
|
|
16941
|
+
});
|
|
16897
16942
|
// Clear previous unsubscribes on new connection (prevent memory leak)
|
|
16898
16943
|
this.unsubscribes.forEach(unsub => unsub());
|
|
16899
16944
|
this.unsubscribes = [];
|
|
@@ -16910,11 +16955,26 @@ class WalletEventsManager {
|
|
|
16910
16955
|
* Disconnect from real-time events
|
|
16911
16956
|
*/
|
|
16912
16957
|
disconnect() {
|
|
16958
|
+
// Clear gave-up flag to prevent auto-reconnect after intentional disconnect
|
|
16959
|
+
this.reconnectGaveUp = false;
|
|
16960
|
+
this.stateChangeUnsubscribe?.();
|
|
16961
|
+
this.stateChangeUnsubscribe = undefined;
|
|
16913
16962
|
this.unsubscribes.forEach(unsub => unsub());
|
|
16914
16963
|
this.unsubscribes = [];
|
|
16915
16964
|
this.client?.disconnect();
|
|
16916
16965
|
this.client = null;
|
|
16917
16966
|
}
|
|
16967
|
+
/**
|
|
16968
|
+
* Full cleanup - disconnect and remove all subscriptions including auth listener
|
|
16969
|
+
* Call this when completely done with the manager (e.g., SDK disposal)
|
|
16970
|
+
*/
|
|
16971
|
+
destroy() {
|
|
16972
|
+
this.disconnect();
|
|
16973
|
+
this.authEventUnsubscribe?.();
|
|
16974
|
+
this.authEventUnsubscribe = undefined;
|
|
16975
|
+
this.reconnectGaveUp = false;
|
|
16976
|
+
this.lastSubscriptions = { wallets: [], chains: [] };
|
|
16977
|
+
}
|
|
16918
16978
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
16919
16979
|
// Subscription Methods (v1.2.0)
|
|
16920
16980
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -16939,6 +16999,8 @@ class WalletEventsManager {
|
|
|
16939
16999
|
if (!this.client) {
|
|
16940
17000
|
throw new Error('Not connected. Call connect() first.');
|
|
16941
17001
|
}
|
|
17002
|
+
// Save subscriptions for auto-resubscribe on reconnect
|
|
17003
|
+
this.lastSubscriptions.wallets = wallets;
|
|
16942
17004
|
return this.client.subscribeWallets(wallets);
|
|
16943
17005
|
}
|
|
16944
17006
|
/**
|
|
@@ -16960,6 +17022,8 @@ class WalletEventsManager {
|
|
|
16960
17022
|
if (!this.client) {
|
|
16961
17023
|
throw new Error('Not connected. Call connect() first.');
|
|
16962
17024
|
}
|
|
17025
|
+
// Save subscriptions for auto-resubscribe on reconnect
|
|
17026
|
+
this.lastSubscriptions.chains = chains;
|
|
16963
17027
|
return this.client.subscribeChains(chains);
|
|
16964
17028
|
}
|
|
16965
17029
|
/**
|
|
@@ -17049,6 +17113,36 @@ class WalletEventsManager {
|
|
|
17049
17113
|
isConnected() {
|
|
17050
17114
|
return this.getState() === 'connected';
|
|
17051
17115
|
}
|
|
17116
|
+
/**
|
|
17117
|
+
* Check if WS reconnection gave up (exhausted all attempts)
|
|
17118
|
+
* Used to determine if we should retry on token refresh
|
|
17119
|
+
*/
|
|
17120
|
+
hasReconnectGivenUp() {
|
|
17121
|
+
return this.reconnectGaveUp;
|
|
17122
|
+
}
|
|
17123
|
+
/**
|
|
17124
|
+
* Retry connection after token refresh
|
|
17125
|
+
* Called when auth tokens are refreshed and WS had previously given up
|
|
17126
|
+
* Automatically resubscribes to previous subscriptions
|
|
17127
|
+
*/
|
|
17128
|
+
async retryAfterTokenRefresh() {
|
|
17129
|
+
if (!this.reconnectGaveUp) {
|
|
17130
|
+
return; // Not in gave-up state, nothing to retry
|
|
17131
|
+
}
|
|
17132
|
+
try {
|
|
17133
|
+
await this.connect();
|
|
17134
|
+
// Restore previous subscriptions
|
|
17135
|
+
if (this.lastSubscriptions.wallets.length > 0) {
|
|
17136
|
+
await this.subscribeWallets(this.lastSubscriptions.wallets);
|
|
17137
|
+
}
|
|
17138
|
+
if (this.lastSubscriptions.chains.length > 0) {
|
|
17139
|
+
await this.subscribeChains(this.lastSubscriptions.chains);
|
|
17140
|
+
}
|
|
17141
|
+
}
|
|
17142
|
+
catch (error) {
|
|
17143
|
+
console.warn('[WalletEventsManager] Retry after token refresh failed:', error);
|
|
17144
|
+
}
|
|
17145
|
+
}
|
|
17052
17146
|
/**
|
|
17053
17147
|
* Get connection info (wallets, active chains)
|
|
17054
17148
|
*/
|
|
@@ -17253,7 +17347,7 @@ class PersSDK {
|
|
|
17253
17347
|
}
|
|
17254
17348
|
// Listen for login success events (both fresh login and session restoration)
|
|
17255
17349
|
this._events.subscribe((event) => {
|
|
17256
|
-
if (event.level === 'success' && (event.type === '
|
|
17350
|
+
if (event.level === 'success' && (event.type === 'login_success' || event.type === 'session_restored')) {
|
|
17257
17351
|
// Auto-connect and subscribe to wallet events (fire and forget, log errors)
|
|
17258
17352
|
this.connectWalletEvents().catch((err) => {
|
|
17259
17353
|
console.warn('[PersSDK] Failed to auto-connect wallet events:', err.message);
|
|
@@ -39975,18 +40069,7 @@ const useWeb3 = () => {
|
|
|
39975
40069
|
* ```
|
|
39976
40070
|
*
|
|
39977
40071
|
* @example
|
|
39978
|
-
* **With
|
|
39979
|
-
* ```typescript
|
|
39980
|
-
* const { tokenBalances, isLoading } = useTokenBalances({
|
|
39981
|
-
* accountAddress: walletAddress!,
|
|
39982
|
-
* availableTokens,
|
|
39983
|
-
* autoLoad: true,
|
|
39984
|
-
* refreshInterval: 30000 // Refresh every 30 seconds
|
|
39985
|
-
* });
|
|
39986
|
-
* ```
|
|
39987
|
-
*
|
|
39988
|
-
* @example
|
|
39989
|
-
* **With Wallet Events (Real-time):**
|
|
40072
|
+
* **With Wallet Events (Real-time):
|
|
39990
40073
|
* ```typescript
|
|
39991
40074
|
* // Auto-refresh on Transfer, Approval, and other blockchain events
|
|
39992
40075
|
* const { tokenBalances } = useTokenBalances({
|
|
@@ -40121,28 +40204,18 @@ function useTokenBalances(options) {
|
|
|
40121
40204
|
loadBalances();
|
|
40122
40205
|
}
|
|
40123
40206
|
}, [autoLoad, isAvailable, availableTokens.length, loadBalances]);
|
|
40124
|
-
//
|
|
40207
|
+
// Deprecated: Fallback polling interval (prefer wallet events)
|
|
40208
|
+
// Kept for backward compatibility and edge cases where events might not work
|
|
40125
40209
|
react.useEffect(() => {
|
|
40126
|
-
if (
|
|
40210
|
+
if (refreshInterval <= 0 || !isAvailable)
|
|
40127
40211
|
return;
|
|
40128
|
-
// Subscribe to transaction domain events
|
|
40129
|
-
const unsubscribe = sdk.events.subscribe((event) => {
|
|
40130
|
-
if (event.domain === 'transaction' && event.type === 'transaction_completed') {
|
|
40131
|
-
console.log('[useTokenBalances] Transaction completed, refreshing balances...');
|
|
40132
|
-
loadBalances();
|
|
40133
|
-
}
|
|
40134
|
-
}, { domains: ['transaction'] });
|
|
40135
|
-
// Also set up a fallback polling interval (much longer than before)
|
|
40136
|
-
// This handles cases where events might be missed
|
|
40137
|
-
const fallbackInterval = Math.max(refreshInterval, 60000); // Minimum 1 minute
|
|
40138
40212
|
const intervalId = setInterval(() => {
|
|
40139
40213
|
loadBalances();
|
|
40140
|
-
},
|
|
40214
|
+
}, refreshInterval);
|
|
40141
40215
|
return () => {
|
|
40142
|
-
unsubscribe();
|
|
40143
40216
|
clearInterval(intervalId);
|
|
40144
40217
|
};
|
|
40145
|
-
}, [
|
|
40218
|
+
}, [refreshInterval, isAvailable, loadBalances]);
|
|
40146
40219
|
// Wallet events refresh: listen for real-time blockchain events
|
|
40147
40220
|
// Refreshes on ANY wallet domain event (Transfer, TransferSingle, etc.)
|
|
40148
40221
|
// Debouncing prevents excessive API calls during rapid events
|
|
@@ -41175,12 +41248,40 @@ const useBusiness = () => {
|
|
|
41175
41248
|
|
|
41176
41249
|
const useCampaigns = () => {
|
|
41177
41250
|
const { sdk, isInitialized, isAuthenticated } = usePersSDK();
|
|
41178
|
-
|
|
41251
|
+
/**
|
|
41252
|
+
* Get active campaigns with optional filters and include relations
|
|
41253
|
+
*
|
|
41254
|
+
* @param options - Filter, pagination, and include options
|
|
41255
|
+
* @returns Promise resolving to paginated active campaigns
|
|
41256
|
+
*
|
|
41257
|
+
* @example
|
|
41258
|
+
* ```typescript
|
|
41259
|
+
* // Simple: get active campaigns with trigger sources
|
|
41260
|
+
* const { data: campaigns } = await getActiveCampaigns({ include: ['triggerSources'] });
|
|
41261
|
+
*
|
|
41262
|
+
* // With pagination
|
|
41263
|
+
* const { data, pagination } = await getActiveCampaigns({
|
|
41264
|
+
* page: 1,
|
|
41265
|
+
* limit: 10,
|
|
41266
|
+
* include: ['triggerSources', 'businesses']
|
|
41267
|
+
* });
|
|
41268
|
+
*
|
|
41269
|
+
* // Filter by tag
|
|
41270
|
+
* const { data } = await getActiveCampaigns({ tag: 'summer-promo' });
|
|
41271
|
+
*
|
|
41272
|
+
* // Filter by business
|
|
41273
|
+
* const { data } = await getActiveCampaigns({ businessId: 'business-123' });
|
|
41274
|
+
* ```
|
|
41275
|
+
*/
|
|
41276
|
+
const getActiveCampaigns = react.useCallback(async (options) => {
|
|
41179
41277
|
if (!isInitialized || !sdk) {
|
|
41180
41278
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
41181
41279
|
}
|
|
41182
41280
|
try {
|
|
41183
|
-
const result = await sdk.campaigns.getCampaigns({
|
|
41281
|
+
const result = await sdk.campaigns.getCampaigns({
|
|
41282
|
+
active: true,
|
|
41283
|
+
...options
|
|
41284
|
+
});
|
|
41184
41285
|
return result;
|
|
41185
41286
|
}
|
|
41186
41287
|
catch (error) {
|
|
@@ -41280,12 +41381,38 @@ const useCampaigns = () => {
|
|
|
41280
41381
|
}
|
|
41281
41382
|
}, [sdk, isInitialized]);
|
|
41282
41383
|
// Admin methods
|
|
41283
|
-
|
|
41384
|
+
/**
|
|
41385
|
+
* Admin: Get all campaigns with optional filters and include relations
|
|
41386
|
+
*
|
|
41387
|
+
* @param options - Filter, pagination, and include options (same as getActiveCampaigns but active is optional)
|
|
41388
|
+
* @returns Promise resolving to paginated campaigns
|
|
41389
|
+
*
|
|
41390
|
+
* @example
|
|
41391
|
+
* ```typescript
|
|
41392
|
+
* // Get all campaigns
|
|
41393
|
+
* const { data } = await getAllCampaigns();
|
|
41394
|
+
*
|
|
41395
|
+
* // Get only active campaigns with trigger sources
|
|
41396
|
+
* const { data } = await getAllCampaigns({ active: true, include: ['triggerSources'] });
|
|
41397
|
+
*
|
|
41398
|
+
* // Get inactive campaigns
|
|
41399
|
+
* const { data } = await getAllCampaigns({ active: false });
|
|
41400
|
+
*
|
|
41401
|
+
* // With pagination and sorting
|
|
41402
|
+
* const { data } = await getAllCampaigns({
|
|
41403
|
+
* page: 1,
|
|
41404
|
+
* limit: 20,
|
|
41405
|
+
* sortBy: 'createdAt',
|
|
41406
|
+
* sortOrder: 'DESC'
|
|
41407
|
+
* });
|
|
41408
|
+
* ```
|
|
41409
|
+
*/
|
|
41410
|
+
const getAllCampaigns = react.useCallback(async (options) => {
|
|
41284
41411
|
if (!isInitialized || !sdk) {
|
|
41285
41412
|
throw new Error('SDK not initialized. Call initialize() first.');
|
|
41286
41413
|
}
|
|
41287
41414
|
try {
|
|
41288
|
-
const result = await sdk.campaigns.getCampaigns(
|
|
41415
|
+
const result = await sdk.campaigns.getCampaigns(options);
|
|
41289
41416
|
return result;
|
|
41290
41417
|
}
|
|
41291
41418
|
catch (error) {
|