@explorins/pers-sdk 2.1.33 → 2.1.39

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.
Files changed (110) hide show
  1. package/README.md +7 -0
  2. package/dist/business/api/business-api.d.ts +10 -3
  3. package/dist/business/api/business-api.d.ts.map +1 -1
  4. package/dist/business/index.d.ts +1 -1
  5. package/dist/business/index.d.ts.map +1 -1
  6. package/dist/business/services/business-service.d.ts +2 -2
  7. package/dist/business/services/business-service.d.ts.map +1 -1
  8. package/dist/business.cjs +1 -1
  9. package/dist/business.js +1 -1
  10. package/dist/chunks/{base-token-service-BiSXWqOy.js → base-token-service-N1gwRD8N.js} +2 -2
  11. package/dist/chunks/{base-token-service-BiSXWqOy.js.map → base-token-service-N1gwRD8N.js.map} +1 -1
  12. package/dist/chunks/{base-token-service-CReAW_nz.cjs → base-token-service-W7TU23qU.cjs} +2 -2
  13. package/dist/chunks/{base-token-service-CReAW_nz.cjs.map → base-token-service-W7TU23qU.cjs.map} +1 -1
  14. package/dist/chunks/{business-membership-service-DXLG5fP9.cjs → business-membership-service-Dkb780NX.cjs} +38 -16
  15. package/dist/chunks/business-membership-service-Dkb780NX.cjs.map +1 -0
  16. package/dist/chunks/{business-membership-service-IyY5CkL0.js → business-membership-service-NLoqoFpG.js} +38 -16
  17. package/dist/chunks/business-membership-service-NLoqoFpG.js.map +1 -0
  18. package/dist/chunks/{index-CgbzGLYT.js → index--OssIds0.js} +14 -11
  19. package/dist/chunks/index--OssIds0.js.map +1 -0
  20. package/dist/chunks/{index-B_n8XiMt.cjs → index-C4K-jkRO.cjs} +13 -10
  21. package/dist/chunks/index-C4K-jkRO.cjs.map +1 -0
  22. package/dist/chunks/{pers-sdk-CySmOdzr.js → pers-sdk-CNIfzWYX.js} +298 -62
  23. package/dist/chunks/pers-sdk-CNIfzWYX.js.map +1 -0
  24. package/dist/chunks/{pers-sdk-DgsYyo1X.cjs → pers-sdk-Cwlrl8jb.cjs} +298 -62
  25. package/dist/chunks/pers-sdk-Cwlrl8jb.cjs.map +1 -0
  26. package/dist/chunks/{redemption-service-CVD2PzBO.cjs → redemption-service-KamEndzB.cjs} +15 -1
  27. package/dist/chunks/{redemption-service-CVD2PzBO.cjs.map → redemption-service-KamEndzB.cjs.map} +1 -1
  28. package/dist/chunks/{redemption-service-czBfCP-3.js → redemption-service-w0GMdF0m.js} +15 -1
  29. package/dist/chunks/{redemption-service-czBfCP-3.js.map → redemption-service-w0GMdF0m.js.map} +1 -1
  30. package/dist/chunks/{tenant-manager-DeEuSlk7.cjs → tenant-manager-DR5eSEJw.cjs} +2 -2
  31. package/dist/chunks/{tenant-manager-DeEuSlk7.cjs.map → tenant-manager-DR5eSEJw.cjs.map} +1 -1
  32. package/dist/chunks/{tenant-manager-BQP25Alv.js → tenant-manager-xmYKBFGu.js} +2 -2
  33. package/dist/chunks/{tenant-manager-BQP25Alv.js.map → tenant-manager-xmYKBFGu.js.map} +1 -1
  34. package/dist/chunks/{token-service-BxEO5YVN.js → token-service-BcuDj292.js} +153 -2
  35. package/dist/chunks/token-service-BcuDj292.js.map +1 -0
  36. package/dist/chunks/{token-service-C1xe11OX.cjs → token-service-CnnrCOsg.cjs} +153 -2
  37. package/dist/chunks/token-service-CnnrCOsg.cjs.map +1 -0
  38. package/dist/chunks/{web3-chain-service-BLrjcBTb.js → web3-chain-service-BWRmwmmJ.js} +2 -2
  39. package/dist/chunks/{web3-chain-service-BLrjcBTb.js.map → web3-chain-service-BWRmwmmJ.js.map} +1 -1
  40. package/dist/chunks/{web3-chain-service-Bilgr4M8.cjs → web3-chain-service-D6tBL0F7.cjs} +2 -2
  41. package/dist/chunks/{web3-chain-service-Bilgr4M8.cjs.map → web3-chain-service-D6tBL0F7.cjs.map} +1 -1
  42. package/dist/chunks/{web3-manager-DbfqhJF4.cjs → web3-manager-C-JflQ86.cjs} +4 -4
  43. package/dist/chunks/{web3-manager-DbfqhJF4.cjs.map → web3-manager-C-JflQ86.cjs.map} +1 -1
  44. package/dist/chunks/{web3-manager-BSvr7wJ7.js → web3-manager-Dvcq4xmn.js} +4 -4
  45. package/dist/chunks/{web3-manager-BSvr7wJ7.js.map → web3-manager-Dvcq4xmn.js.map} +1 -1
  46. package/dist/core/auth/dpop/dpop-manager.d.ts +0 -1
  47. package/dist/core/auth/dpop/dpop-manager.d.ts.map +1 -1
  48. package/dist/core/auth/refresh-manager.d.ts +12 -2
  49. package/dist/core/auth/refresh-manager.d.ts.map +1 -1
  50. package/dist/core/auth/services/auth-service.d.ts +10 -3
  51. package/dist/core/auth/services/auth-service.d.ts.map +1 -1
  52. package/dist/core/errors/index.d.ts +6 -6
  53. package/dist/core/errors/index.d.ts.map +1 -1
  54. package/dist/core/events/event-types.d.ts +5 -1
  55. package/dist/core/events/event-types.d.ts.map +1 -1
  56. package/dist/core/pers-api-client.d.ts.map +1 -1
  57. package/dist/core/utils/jwt.function.d.ts +3 -12
  58. package/dist/core/utils/jwt.function.d.ts.map +1 -1
  59. package/dist/core.cjs +6 -6
  60. package/dist/core.js +6 -6
  61. package/dist/index.cjs +7 -7
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +7 -7
  65. package/dist/managers/redemption-manager.d.ts +58 -1
  66. package/dist/managers/redemption-manager.d.ts.map +1 -1
  67. package/dist/managers/token-manager.d.ts +121 -2
  68. package/dist/managers/token-manager.d.ts.map +1 -1
  69. package/dist/node.cjs +6 -6
  70. package/dist/node.js +6 -6
  71. package/dist/package.json +2 -2
  72. package/dist/redemption/services/redemption-service.d.ts +10 -0
  73. package/dist/redemption/services/redemption-service.d.ts.map +1 -1
  74. package/dist/redemption.cjs +1 -1
  75. package/dist/redemption.js +1 -1
  76. package/dist/token/api/token-api.d.ts +79 -1
  77. package/dist/token/api/token-api.d.ts.map +1 -1
  78. package/dist/token/index.d.ts +1 -1
  79. package/dist/token/index.d.ts.map +1 -1
  80. package/dist/token/services/token-service.d.ts +61 -1
  81. package/dist/token/services/token-service.d.ts.map +1 -1
  82. package/dist/token.cjs +2 -2
  83. package/dist/token.js +2 -2
  84. package/dist/trigger-source/api/trigger-source-api.d.ts +9 -10
  85. package/dist/trigger-source/api/trigger-source-api.d.ts.map +1 -1
  86. package/dist/trigger-source/index.d.ts +1 -0
  87. package/dist/trigger-source/index.d.ts.map +1 -1
  88. package/dist/trigger-source/models/index.d.ts +5 -13
  89. package/dist/trigger-source/models/index.d.ts.map +1 -1
  90. package/dist/trigger-source/services/trigger-source-service.d.ts +3 -11
  91. package/dist/trigger-source/services/trigger-source-service.d.ts.map +1 -1
  92. package/dist/trigger-source.cjs +20 -1
  93. package/dist/trigger-source.cjs.map +1 -1
  94. package/dist/trigger-source.js +20 -1
  95. package/dist/trigger-source.js.map +1 -1
  96. package/dist/web3-chain.cjs +2 -2
  97. package/dist/web3-chain.js +2 -2
  98. package/dist/web3-manager.cjs +4 -4
  99. package/dist/web3-manager.js +4 -4
  100. package/dist/web3.cjs +4 -4
  101. package/dist/web3.js +4 -4
  102. package/package.json +2 -2
  103. package/dist/chunks/business-membership-service-DXLG5fP9.cjs.map +0 -1
  104. package/dist/chunks/business-membership-service-IyY5CkL0.js.map +0 -1
  105. package/dist/chunks/index-B_n8XiMt.cjs.map +0 -1
  106. package/dist/chunks/index-CgbzGLYT.js.map +0 -1
  107. package/dist/chunks/pers-sdk-CySmOdzr.js.map +0 -1
  108. package/dist/chunks/pers-sdk-DgsYyo1X.cjs.map +0 -1
  109. package/dist/chunks/token-service-BxEO5YVN.js.map +0 -1
  110. package/dist/chunks/token-service-C1xe11OX.cjs.map +0 -1
@@ -1,16 +1,16 @@
1
1
  'use strict';
2
2
 
3
3
  var persShared = require('@explorins/pers-shared');
4
- var index = require('./index-B_n8XiMt.cjs');
4
+ var index = require('./index-C4K-jkRO.cjs');
5
5
  var user = require('../user.cjs');
6
6
  var userStatus = require('../user-status.cjs');
7
- var tokenService = require('./token-service-C1xe11OX.cjs');
8
- var businessMembershipService = require('./business-membership-service-DXLG5fP9.cjs');
7
+ var tokenService = require('./token-service-CnnrCOsg.cjs');
8
+ var businessMembershipService = require('./business-membership-service-Dkb780NX.cjs');
9
9
  var campaign = require('../campaign.cjs');
10
- var redemptionService = require('./redemption-service-CVD2PzBO.cjs');
10
+ var redemptionService = require('./redemption-service-KamEndzB.cjs');
11
11
  var transactionRequest_builder = require('./transaction-request.builder-D8pIzjYD.cjs');
12
12
  var paymentService = require('./payment-service-Bkw7ZXev.cjs');
13
- var tenantManager = require('./tenant-manager-DeEuSlk7.cjs');
13
+ var tenantManager = require('./tenant-manager-DR5eSEJw.cjs');
14
14
  var paginationUtils = require('./pagination-utils-B2jRHMSO.cjs');
15
15
  var analyticsService = require('./analytics-service-CRs9cpkg.cjs');
16
16
  var donation = require('../donation.cjs');
@@ -416,13 +416,17 @@ class AuthService {
416
416
  * Returns true for:
417
417
  * - Known fatal error codes (REFRESH_TOKEN_EXPIRED, TOKEN_REVOKED, etc.)
418
418
  * - Fatal error codes in error messages (wrapped errors)
419
- * - 401/403 HTTP status codes
420
419
  *
421
- * Returns false for (retryable errors):
420
+ * Returns false for (retryable/recoverable):
422
421
  * - Network errors
423
422
  * - Timeouts
424
423
  * - 5xx server errors
425
424
  * - TOKEN_EXPIRED (normal refresh trigger)
425
+ * - Raw 401/403 without fatal code (should try refresh first)
426
+ *
427
+ * NOTE: We intentionally DO NOT treat raw 401/403 status as fatal.
428
+ * The HTTP client handles 401 by attempting token refresh first.
429
+ * Only if refresh fails WITH a fatal code do we logout.
426
430
  */
427
431
  isDefinitiveAuthFailure(error) {
428
432
  if (!error)
@@ -437,11 +441,12 @@ class AuthService {
437
441
  if (isFatalAuthErrorInMessage(errorMessage)) {
438
442
  return true;
439
443
  }
440
- // Check HTTP status if available
441
- const status = errorAny?.status || errorAny?.response?.status;
442
- if (status === 401 || status === 403) {
443
- return true;
444
- }
444
+ // NOTE: We intentionally DO NOT check HTTP status codes here.
445
+ // A raw 401/403 without a fatal error code should trigger a refresh attempt,
446
+ // not an immediate logout. The HTTP client (pers-api-client.ts) handles this:
447
+ // 1. 401 received → try refresh token
448
+ // 2. Refresh succeeds → retry original request
449
+ // 3. Refresh fails with fatal CODE → then logout
445
450
  // Everything else is considered retryable
446
451
  return false;
447
452
  }
@@ -499,6 +504,9 @@ class AuthService {
499
504
  * Extracts context (tenantId/businessId) from the current refresh token to ensure
500
505
  * the recovered session maintains the same context.
501
506
  *
507
+ * This is a PUBLIC method that can be called by TokenRefreshManager when internal
508
+ * refresh fails, to try external (provider token) recovery before giving up.
509
+ *
502
510
  * @returns true if session was successfully recovered
503
511
  */
504
512
  async attemptProviderTokenRecovery() {
@@ -525,12 +533,17 @@ class AuthService {
525
533
  const contextClaims = refreshToken ? index.decodeJwtPayload(refreshToken) : null;
526
534
  // Re-authenticate using provider token based on auth type
527
535
  // Pass the context from the previous session to avoid MULTIPLE_CONTEXT_SELECTION_REQUIRED
536
+ // Note: In AuthJWTPayload, when accountType=BUSINESS, sub contains the businessId
528
537
  switch (authType) {
529
538
  case persShared.AccountOwnerType.USER:
530
539
  await this.loginUser(providerToken);
531
540
  break;
532
541
  case persShared.AccountOwnerType.BUSINESS:
533
- await this.loginBusiness(providerToken, contextClaims?.businessId ? { businessId: contextClaims.businessId } : undefined);
542
+ // For BUSINESS auth, sub contains the businessId when accountType is BUSINESS
543
+ const businessId = contextClaims?.accountType === persShared.AccountOwnerType.BUSINESS
544
+ ? contextClaims.sub
545
+ : undefined;
546
+ await this.loginBusiness(providerToken, businessId ? { businessId } : undefined);
534
547
  break;
535
548
  case persShared.AccountOwnerType.TENANT:
536
549
  await this.loginTenantAdmin(providerToken, contextClaims?.tenantId ? { tenantId: contextClaims.tenantId } : undefined);
@@ -646,6 +659,8 @@ class TokenRefreshManager {
646
659
  // Retry configuration for transient failures
647
660
  this.MAX_RETRY_ATTEMPTS = 3;
648
661
  this.RETRY_DELAY_MS = 1000;
662
+ // Active refresh promise for deduplication
663
+ this.activeRefreshPromise = null;
649
664
  }
650
665
  /**
651
666
  * Ensures the access token is valid, refreshing if needed.
@@ -746,11 +761,27 @@ class TokenRefreshManager {
746
761
  return new Promise(resolve => setTimeout(resolve, ms));
747
762
  }
748
763
  /**
749
- * @deprecated Use ensureValidToken() instead
764
+ * Attempt token refresh: internal first, then provider token fallback.
765
+ * DEDUPLICATES concurrent calls - all callers share the same promise.
750
766
  */
751
767
  async attemptInternalRefresh() {
752
- const result = await this.attemptRefreshWithRetry();
753
- return result.success;
768
+ if (this.activeRefreshPromise) {
769
+ return this.activeRefreshPromise;
770
+ }
771
+ this.activeRefreshPromise = (async () => {
772
+ const result = await this.attemptRefreshWithRetry();
773
+ if (result.success)
774
+ return result;
775
+ // Internal failed - try provider token recovery
776
+ const recovered = await this.authService.attemptProviderTokenRecovery();
777
+ return recovered ? { success: true, retryable: false } : result;
778
+ })();
779
+ try {
780
+ return await this.activeRefreshPromise;
781
+ }
782
+ finally {
783
+ this.activeRefreshPromise = null;
784
+ }
754
785
  }
755
786
  }
756
787
 
@@ -1298,17 +1329,16 @@ class DPoPManager {
1298
1329
  * Generate a short fingerprint of the public key for debugging
1299
1330
  * This helps identify if the same key is being used across operations
1300
1331
  */
1301
- getPublicKeyFingerprint(publicKey) {
1302
- try {
1303
- // Use the 'x' coordinate of the EC key as a fingerprint
1304
- const x = publicKey.x || '';
1305
- const y = publicKey.y || '';
1306
- return `${x.substring(0, 8)}...${y.substring(0, 4)}`;
1307
- }
1308
- catch {
1309
- return 'unknown';
1310
- }
1311
- }
1332
+ /* private getPublicKeyFingerprint(publicKey: JsonWebKey): string {
1333
+ try {
1334
+ // Use the 'x' coordinate of the EC key as a fingerprint
1335
+ const x = publicKey.x || '';
1336
+ const y = publicKey.y || '';
1337
+ return `${x.substring(0, 8)}...${y.substring(0, 4)}`;
1338
+ } catch {
1339
+ return 'unknown';
1340
+ }
1341
+ } */
1312
1342
  /**
1313
1343
  * Clears DPoP keys (e.g. on logout)
1314
1344
  */
@@ -1557,7 +1587,7 @@ class DefaultAuthProvider {
1557
1587
  /** SDK package name */
1558
1588
  const SDK_NAME = "@explorins/pers-sdk";
1559
1589
  /** SDK version - injected from package.json at build time */
1560
- const SDK_VERSION = "2.1.33";
1590
+ const SDK_VERSION = "2.1.39";
1561
1591
  /** Full SDK identifier for headers */
1562
1592
  const SDK_USER_AGENT = `${SDK_NAME}/${SDK_VERSION}`;
1563
1593
 
@@ -1667,12 +1697,16 @@ class PersApiClient {
1667
1697
  }
1668
1698
  const { retryCount = 0, responseType = 'json', bypassAuth = false } = options || {};
1669
1699
  const url = `${this.apiRoot}${endpoint}`;
1670
- // SMART TOKEN VALIDATION: Only check if we suspect the token might be expired
1700
+ // TOKEN VALIDATION: Ensure token is valid before request
1701
+ // This blocks the request until token validation completes - prevents 401s from expired tokens
1671
1702
  if (!bypassAuth && this.mergedConfig.authProvider && retryCount === 0) {
1672
- // Fire-and-forget validation - don't block the request unless we know there's an issue
1673
- this.ensureValidToken().catch(error => {
1674
- console.debug('[PersApiClient] Background token validation failed:', error);
1675
- });
1703
+ try {
1704
+ await this.ensureValidToken();
1705
+ }
1706
+ catch (error) {
1707
+ console.debug('[PersApiClient] Token validation failed:', error);
1708
+ // Continue with request - it will fail with 401 and trigger retry logic
1709
+ }
1676
1710
  }
1677
1711
  const requestOptions = {
1678
1712
  headers: await this.getHeaders(!bypassAuth, method, url),
@@ -1700,49 +1734,63 @@ class PersApiClient {
1700
1734
  return result;
1701
1735
  }
1702
1736
  catch (error) {
1703
- // Error handling - proactive token refresh should prevent most 401s
1704
1737
  const status = index.ErrorUtils.getStatus(error);
1705
1738
  const errorMessage = index.ErrorUtils.getMessage(error);
1706
- // Handle 401 errors centrally through AuthService
1739
+ // Handle 401 Unauthorized errors
1707
1740
  if (status === 401) {
1708
1741
  const backendError = index.ErrorUtils.extractBackendErrorDetails(error);
1709
- // Check for FATAL auth error CODES (not just 401 status)
1710
- // Fatal codes: REFRESH_TOKEN_EXPIRED, TOKEN_REVOKED, etc. immediate logout
1711
- // Non-fatal codes: TOKEN_EXPIRED → try refresh first
1742
+ // ===========================================
1743
+ // FATAL AUTH ERRORSImmediate logout
1744
+ // ===========================================
1745
+ // Fatal codes: REFRESH_TOKEN_EXPIRED, TOKEN_REVOKED, INVALID_REFRESH_TOKEN, etc.
1712
1746
  if (this.authService.isFatalAuthError(backendError.code)) {
1713
- // Definitive auth failure - no retry, session is invalid
1747
+ console.warn(`[PersApiClient] Fatal auth error: ${backendError.code}`);
1714
1748
  await this.authService.handleAuthFailure();
1715
1749
  this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
1716
1750
  throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
1717
1751
  }
1718
- // If this IS a refresh request that failed with 401, don't retry to avoid infinite loop
1752
+ // ===========================================
1753
+ // REFRESH REQUEST FAILED → Logout (prevents infinite loop)
1754
+ // ===========================================
1719
1755
  if (options?.isRefreshRequest) {
1720
- // Refresh failed - this is a real auth failure
1756
+ console.warn('[PersApiClient] Refresh request itself failed with 401');
1721
1757
  await this.authService.handleAuthFailure();
1722
1758
  this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
1723
1759
  throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
1724
1760
  }
1725
- // TOKEN_EXPIRED or unknown 401: try refresh once, then retry
1761
+ // ===========================================
1762
+ // RETRYABLE 401 (TOKEN_EXPIRED) → Try refresh, then retry
1763
+ // ===========================================
1726
1764
  if (retryCount === 0 && this.mergedConfig.authProvider) {
1727
- try {
1728
- const refreshSuccessful = await this.refreshManager.attemptInternalRefresh();
1729
- if (refreshSuccessful) {
1730
- // Emit TOKEN_REFRESHED event so WS clients can retry if they gave up
1731
- this._events?.emitSuccess({
1732
- type: 'token_refreshed',
1733
- domain: 'authentication',
1734
- userMessage: 'Authentication token refreshed',
1735
- });
1736
- // Retry with new token
1737
- return await this.request(method, endpoint, body, { ...options, retryCount: 1 });
1738
- }
1765
+ const refreshResult = await this.refreshManager.attemptInternalRefresh();
1766
+ if (refreshResult.success) {
1767
+ // Refresh succeeded → retry request with new token
1768
+ this._events?.emitSuccess({
1769
+ type: 'token_refreshed',
1770
+ domain: 'authentication',
1771
+ userMessage: 'Authentication token refreshed',
1772
+ });
1773
+ return await this.request(method, endpoint, body, { ...options, retryCount: 1 });
1774
+ }
1775
+ // Refresh failed - check if it's a definitive failure
1776
+ if (!refreshResult.retryable) {
1777
+ // Non-retryable failure (e.g., refresh token expired) → logout
1778
+ console.warn('[PersApiClient] Refresh failed with non-retryable error, logging out');
1779
+ await this.authService.handleAuthFailure();
1739
1780
  }
1740
- catch (refreshError) {
1741
- // Refresh failed - fall through to handleAuthFailure
1781
+ else {
1782
+ // Retryable failure (network error, etc.) DON'T logout, let app retry later
1783
+ console.warn('[PersApiClient] Refresh failed with retryable error, NOT logging out');
1742
1784
  }
1785
+ this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
1786
+ throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
1743
1787
  }
1744
- // All recovery attempts failed
1745
- await this.authService.handleAuthFailure();
1788
+ // ===========================================
1789
+ // RETRY FAILED (retryCount > 0) → Something wrong, but DON'T logout
1790
+ // ===========================================
1791
+ // We already refreshed successfully, but retry still got 401
1792
+ // This is unexpected - don't logout, let app investigate
1793
+ console.warn('[PersApiClient] Retry with new token still got 401 - not logging out');
1746
1794
  this.emitErrorEvent(backendError, errorMessage, endpoint, method, status, error);
1747
1795
  throw new index.AuthenticationError(errorMessage, endpoint, method, backendError);
1748
1796
  }
@@ -1768,9 +1816,9 @@ class PersApiClient {
1768
1816
  }); */
1769
1817
  this._events?.emitError({
1770
1818
  domain: errorDetails.domain || 'external',
1771
- type: errorDetails.code || 'API_ERROR',
1772
- userMessage: errorDetails.message || errorMessage, // Event system uses userMessage for display
1773
- code: errorDetails.code,
1819
+ type: 'api_error', // Event type discriminator (fixed value)
1820
+ userMessage: errorDetails.message || errorMessage,
1821
+ code: errorDetails.code, // Actual error code from backend
1774
1822
  details: {
1775
1823
  endpoint,
1776
1824
  method,
@@ -3406,6 +3454,107 @@ class TokenManager {
3406
3454
  async getTokenByContract(contractAddress, contractTokenId = null) {
3407
3455
  return this.tokenService.getTokenByContractAddress(contractAddress, contractTokenId);
3408
3456
  }
3457
+ /**
3458
+ * Get all token metadata with filtering, pagination, and include relations
3459
+ *
3460
+ * Retrieves token metadata (rewards/stamps) with server-side filtering, pagination,
3461
+ * and optional include relations for additional data.
3462
+ * Useful for displaying rewards (ERC1155) or stamps (ERC721) in admin tables.
3463
+ * Non-admin users always get active metadata only.
3464
+ *
3465
+ * @param options - Filter, pagination, and include options
3466
+ * @returns Promise resolving to paginated token metadata
3467
+ *
3468
+ * @example Get paginated rewards with counts
3469
+ * ```typescript
3470
+ * const rewards = await sdk.tokens.getTokenMetadata({
3471
+ * tokenType: 'ERC1155',
3472
+ * active: true,
3473
+ * page: 1,
3474
+ * limit: 10,
3475
+ * sortBy: 'name',
3476
+ * sortOrder: 'ASC',
3477
+ * include: ['mintCount', 'burnCount', 'token']
3478
+ * });
3479
+ *
3480
+ * rewards.data.forEach(r => {
3481
+ * console.log(`${r.name}: ${r.mintCount} minted, ${r.burnCount} burned`);
3482
+ * console.log(`Contract: ${r.included?.token?.contractAddress}`);
3483
+ * });
3484
+ * ```
3485
+ *
3486
+ * @example Get stamps with owner business
3487
+ * ```typescript
3488
+ * const stamps = await sdk.tokens.getTokenMetadata({
3489
+ * tokenType: 'ERC721',
3490
+ * search: 'gold',
3491
+ * include: ['ownerBusiness', 'token']
3492
+ * });
3493
+ *
3494
+ * stamps.data.forEach(s => {
3495
+ * console.log(`${s.name} owned by ${s.included?.ownerBusiness?.displayName}`);
3496
+ * });
3497
+ * ```
3498
+ */
3499
+ async getTokenMetadata(options) {
3500
+ return this.tokenService.getTokenMetadata(options);
3501
+ }
3502
+ /**
3503
+ * Get rewards (ERC1155 token metadata) with filtering, pagination, and include relations
3504
+ *
3505
+ * Convenience method for fetching reward metadata. Rewards are ERC1155 tokens
3506
+ * that represent collectible items, vouchers, or other redeemable rewards.
3507
+ *
3508
+ * @param options - Filter, pagination, and include options (tokenType is set automatically)
3509
+ * @returns Promise resolving to paginated reward metadata
3510
+ *
3511
+ * @example Get active rewards with mint counts
3512
+ * ```typescript
3513
+ * const rewards = await sdk.tokens.getRewards({
3514
+ * active: true,
3515
+ * limit: 10,
3516
+ * include: ['mintCount', 'burnCount', 'token', 'ownerBusiness']
3517
+ * });
3518
+ *
3519
+ * rewards.data.forEach(r => {
3520
+ * console.log(`${r.name}: ${r.mintCount ?? 0} minted`);
3521
+ * if (r.included?.token) {
3522
+ * console.log(` Chain: ${r.included.token.chainId}, Contract: ${r.included.token.contractAddress}`);
3523
+ * }
3524
+ * });
3525
+ * ```
3526
+ */
3527
+ async getRewards(options) {
3528
+ return this.tokenService.getRewards(options);
3529
+ }
3530
+ /**
3531
+ * Get stamps (ERC721 token metadata) with filtering, pagination, and include relations
3532
+ *
3533
+ * Convenience method for fetching stamp metadata. Stamps are ERC721 tokens
3534
+ * that represent achievements, badges, or collectible status markers.
3535
+ *
3536
+ * @param options - Filter, pagination, and include options (tokenType is set automatically)
3537
+ * @returns Promise resolving to paginated stamp metadata
3538
+ *
3539
+ * @example Get active stamps with all includes
3540
+ * ```typescript
3541
+ * const stamps = await sdk.tokens.getStamps({
3542
+ * active: true,
3543
+ * limit: 10,
3544
+ * include: ['mintCount', 'burnCount', 'token', 'ownerBusiness']
3545
+ * });
3546
+ *
3547
+ * stamps.data.forEach(s => {
3548
+ * console.log(`${s.name}: ${s.mintCount ?? 0} minted`);
3549
+ * if (s.included?.ownerBusiness) {
3550
+ * console.log(` Owner: ${s.included.ownerBusiness.displayName}`);
3551
+ * }
3552
+ * });
3553
+ * ```
3554
+ */
3555
+ async getStamps(options) {
3556
+ return this.tokenService.getStamps(options);
3557
+ }
3409
3558
  /**
3410
3559
  * Admin: Create new token
3411
3560
  *
@@ -3497,6 +3646,32 @@ class TokenManager {
3497
3646
  async toggleTokenActive(tokenId) {
3498
3647
  return this.tokenService.toggleTokenActive(tokenId);
3499
3648
  }
3649
+ /**
3650
+ * Admin: Delete token metadata (soft delete)
3651
+ *
3652
+ * Soft deletes token metadata by setting deletedAt timestamp.
3653
+ * Requires administrator privileges. Will fail with 409 Conflict
3654
+ * if metadata is currently in use by active campaigns or redemptions.
3655
+ *
3656
+ * @param metadataId - ID of the token metadata to delete
3657
+ * @throws {PersApiError} When not authenticated as admin
3658
+ * @throws {PersApiError} 409 Conflict if metadata is in use
3659
+ *
3660
+ * @example
3661
+ * ```typescript
3662
+ * try {
3663
+ * await sdk.tokens.deleteTokenMetadata('metadata-123');
3664
+ * console.log('Token metadata deleted');
3665
+ * } catch (error) {
3666
+ * if (error.statusCode === 409) {
3667
+ * console.log('Cannot delete: metadata is used by campaigns/redemptions');
3668
+ * }
3669
+ * }
3670
+ * ```
3671
+ */
3672
+ async deleteTokenMetadata(metadataId) {
3673
+ return this.tokenService.deleteTokenMetadata(metadataId);
3674
+ }
3500
3675
  /**
3501
3676
  * Get the full token SDK for advanced operations
3502
3677
  *
@@ -5310,6 +5485,52 @@ class RedemptionManager {
5310
5485
  async getRedemptions(options) {
5311
5486
  return this.redemptionService.getRedemptions(options);
5312
5487
  }
5488
+ /**
5489
+ * Get a specific redemption by ID
5490
+ *
5491
+ * Retrieves detailed information about a specific redemption offer.
5492
+ * Useful when you already have the redemption ID and need full details.
5493
+ *
5494
+ * @param id - Redemption UUID
5495
+ * @param include - Optional relations to include: 'redeemCount'
5496
+ * @returns Promise resolving to the redemption
5497
+ *
5498
+ * @example Basic usage
5499
+ * ```typescript
5500
+ * const redemption = await sdk.redemptions.getRedemptionById('7baf4d39-0bd6-45ca-9c66-8c0d655767c3');
5501
+ * console.log(redemption.name);
5502
+ * console.log(redemption.description);
5503
+ * ```
5504
+ *
5505
+ * @example With redeem count
5506
+ * ```typescript
5507
+ * const redemption = await sdk.redemptions.getRedemptionById(
5508
+ * 'redemption-123',
5509
+ * ['redeemCount']
5510
+ * );
5511
+ * console.log(`${redemption.name} has been redeemed ${redemption.redeemCount} times`);
5512
+ * ```
5513
+ *
5514
+ * @example Get redemption details for display
5515
+ * ```typescript
5516
+ * const redemption = await sdk.redemptions.getRedemptionById(id);
5517
+ *
5518
+ * console.log('Redemption Details:');
5519
+ * console.log(`Name: ${redemption.name}`);
5520
+ * console.log(`Description: ${redemption.description}`);
5521
+ * console.log(`Active: ${redemption.isActive}`);
5522
+ *
5523
+ * if (redemption.tokenUnits?.length) {
5524
+ * console.log('Cost:');
5525
+ * redemption.tokenUnits.forEach(unit => {
5526
+ * console.log(` ${unit.amount} ${unit.token.symbol}`);
5527
+ * });
5528
+ * }
5529
+ * ```
5530
+ */
5531
+ async getRedemptionById(id, include) {
5532
+ return this.redemptionService.getRedemptionById(id, include);
5533
+ }
5313
5534
  /**
5314
5535
  * Get available redemption types
5315
5536
  *
@@ -5844,6 +6065,21 @@ class RedemptionManager {
5844
6065
  async deleteRedemptionType(id) {
5845
6066
  return this.redemptionService.deleteRedemptionType(id);
5846
6067
  }
6068
+ /**
6069
+ * Delete a redemption (soft delete)
6070
+ *
6071
+ * @param id - Redemption ID to delete
6072
+ * @returns Promise resolving to true if deleted successfully
6073
+ *
6074
+ * @example
6075
+ * ```typescript
6076
+ * const success = await sdk.redemptions.deleteRedemption('redemption-123');
6077
+ * console.log('Deleted:', success);
6078
+ * ```
6079
+ */
6080
+ async deleteRedemption(id) {
6081
+ return this.redemptionService.deleteRedemption(id);
6082
+ }
5847
6083
  /**
5848
6084
  * Get the full redemption service for advanced operations
5849
6085
  *
@@ -10713,4 +10949,4 @@ exports.createPersEventsClient = createPersEventsClient;
10713
10949
  exports.createPersSDK = createPersSDK;
10714
10950
  exports.isFatalAuthErrorInMessage = isFatalAuthErrorInMessage;
10715
10951
  exports.mergeWithDefaults = mergeWithDefaults;
10716
- //# sourceMappingURL=pers-sdk-DgsYyo1X.cjs.map
10952
+ //# sourceMappingURL=pers-sdk-Cwlrl8jb.cjs.map